poj 3114(强连通缩点+SPFA)
题目链接:http://poj.org/problem?id=3114
思路:题目要求很简单,就是求两点之间的花费的最短时间,不过有一个要求:如果这两个city属于同一个国家,则花费时间为0。如何判断一个是属于同一个国家呢?就要缩点了,这样属于同一个强连通分量的点就是属于同一个国家了。然后就是SPFA求最短路。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stack> 6 #include<vector> 7 #include<queue> 8 using namespace std; 9 #define MAXN 555 10 #define inf 1<<30 11 12 struct Edge{ 13 int v,w; 14 Edge(int vv,int ww):v(vv),w(ww){} 15 }; 16 17 int dfn[MAXN],low[MAXN],color[MAXN]; 18 bool mark[MAXN]; 19 int dist[MAXN]; 20 int n,m,k,cnt,_count; 21 22 vector<vector<Edge> >map; 23 stack<int>S; 24 25 void Tarjan(int u) 26 { 27 dfn[u]=low[u]=++cnt; 28 mark[u]=true; 29 S.push(u); 30 for(int i=0;i<map[u].size();i++){ 31 int v=map[u][i].v; 32 if(dfn[v]==0){ 33 Tarjan(v); 34 low[u]=min(low[u],low[v]); 35 }else if(mark[v]){ 36 low[u]=min(low[u],dfn[v]); 37 } 38 } 39 if(low[u]==dfn[u]){ 40 int v; 41 _count++; 42 do{ 43 v=S.top(); 44 S.pop(); 45 mark[v]=false; 46 color[v]=_count; 47 }while(u!=v); 48 } 49 } 50 51 int SPFA(int st,int ed) 52 { 53 for(int i=1;i<=n;i++)dist[i]=inf; 54 dist[st]=0; 55 queue<int>Q; 56 Q.push(st); 57 while(!Q.empty()){ 58 int u=Q.front(); 59 Q.pop(); 60 mark[u]=false; 61 for(int i=0;i<map[u].size();i++){ 62 int v=map[u][i].v,w=map[u][i].w; 63 if(color[u]==color[v])w=0; 64 if(dist[u]+w<dist[v]){ 65 dist[v]=dist[u]+w; 66 if(!mark[v]){ mark[v]=true;Q.push(v); } 67 } 68 } 69 } 70 return dist[ed]<inf; 71 } 72 73 int main() 74 { 75 int u,v,w; 76 while(~scanf("%d",&n)&&n){ 77 scanf("%d",&m); 78 map.clear();map.resize(n+2); 79 while(m--){ 80 scanf("%d%d%d",&u,&v,&w); 81 map[u].push_back(Edge(v,w)); 82 } 83 cnt=_count=0; 84 memset(dfn,0,sizeof(dfn)); 85 memset(mark,false,sizeof(mark)); 86 for(int i=1;i<=n;i++){ 87 if(dfn[i]==0)Tarjan(i); 88 } 89 scanf("%d",&k); 90 while(k--){ 91 scanf("%d%d",&u,&v); 92 if(SPFA(u,v))printf("%d\n",dist[v]); 93 else puts("Nao e possivel entregar a carta"); 94 } 95 puts(""); 96 } 97 return 0; 98 }