1. 程式人生 > >USACO 2014 US Open Dueling GPS's /// SPFA

USACO 2014 US Open Dueling GPS's /// SPFA

struct 圖片 scanf long str const 將不 scan cli

題目大意:

給定n個點m條邊的有向圖

有兩個GPS 分別認為 A[i]到B[i] 的一條邊的花費是P[i]、Q[i]

當當前走的邊不是GPS認為的最短路上的邊就會被警告

即兩個GPS都不認為是最短路上的邊時 會被警告兩次

求從點1走到點n被警告次數最少是多少次

https://blog.csdn.net/oakley_/article/details/52510465

按P[i]反向建圖 再從n跑最短路到1 然後遍歷所有的邊判斷將不是最短路的邊C[i]+1

Q[i]也同樣 最後按C[i]從1跑最短路到n 得到的就是被最少警告的次數

為什麽要反向建圖跑最短路?

因為導航系統到了點2 點3 點4...之後仍然要導航到目標點n

那麽就變成了點2到點n的最短路 點3到點n的最短路 ...

所以反向是要使得求出dis[i]為 點i到點n的最短路

若是正向會是 點1到點n的最短路 與要求不符

技術分享圖片
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define LL long long
#define gcd(i,j) __gcd(i,j)
#define mem(i,j) memset(i,j,sizeof(i))
#define inc(i,j,k) for(int i=j;i<=k;i++)
#define
dec(i,j,k) for(int i=j;i>=k;i--) const int N=1e4+5; const int M=1e5+5; int n,m,C[M]; int A[M],B[M],P[M],Q[M]; struct NODE { int to,len,nt; }e[M]; int head[N], tot; void init() { tot=1; mem(head,0); } void addE(int u,int v,int w) { e[tot].to=v; e[tot].len=w; e[tot].nt=head[u]; head[u]=tot++; }
int dis[N]; bool inq[N]; void SPFA(int s) { mem(dis,INF); queue<int>q; while(!q.empty()) q.pop(); dis[s]=0; q.push(s); while(!q.empty()) { int u=q.front(); q.pop(); inq[u]=0; for(int i=head[u];i;i=e[i].nt) { int v=e[i].to; if(dis[v]<=dis[u]+e[i].len) continue; dis[v]=dis[u]+e[i].len; if(!inq[v]) inq[v]=1, q.push(v); } } } void check(int u[],int v[],int w[],int st) { init(); inc(i,1,m) addE(u[i],v[i],w[i]); SPFA(st); inc(i,1,m) if(dis[v[i]]!=dis[u[i]]+w[i]) C[i]++; } int main() { while(~scanf("%d%d",&n,&m)) { inc(i,1,m) scanf("%d%d%d%d",&A[i],&B[i],&P[i],&Q[i]); mem(C,0); check(B,A,P,n); check(B,A,Q,n); check(A,B,C,1); printf("%d\n",dis[n]); } return 0; }
View Code

USACO 2014 US Open Dueling GPS's /// SPFA