poj 3114 Countries in War
http://poj.org/problem?id=3114
题目大意:战争期间的通信问题,同一个国家的城市间可以互相通信,距离可视为零,不同国家的城市间根据所给路径,求解最短路.
思路:对于有向图中的环,先进行缩点重建图,然后对每个点直接spfa。
注意:重建图后不一定是棵树,所以不能用lca。
View Code
#include<stdio.h> #include<string.h> #include<stdlib.h> #include<stack> #include<iostream> #include<utility> using namespace std; const int maxn = 505; const int inf = 0xffffff; struct nd { int u,v,w,next; }edge[maxn*maxn]; int head[maxn],vis[maxn],dfn[maxn],low[maxn],belong[maxn],in[maxn],dis[maxn][maxn],head2[maxn],qeu[maxn*10]; int ecnt,idx,cnt,n,m; stack<int>st; void add(int u,int v,int w) { edge[ecnt].u = u; edge[ecnt].v = v; edge[ecnt].w = w; edge[ecnt].next = head[u]; head[u] = ecnt++; } void tarjan(int u) { int i,v; dfn[u] = low[u] = ++idx; st.push(u); vis[u] = 1; for(i = head[u]; i != -1; i = edge[i].next) { v = edge[i].v; if(!dfn[v]){ tarjan(v); low[u] = min(low[v],low[u]); }else if(vis[v]) low[u] = min(dfn[v],low[u]); } if(dfn[u]==low[u]){ cnt++; do{ v = st.top(); st.pop(); vis[v] = 0; belong[v] = cnt; }while(v!=u); } } void spfa(int s) { int i,j,k,ts = 0,te = 1; memset(vis,0,sizeof(vis)); qeu[ts] = s; dis[s][s] = 0; while(ts<te) { k = qeu[ts]; vis[k] = 0; for(i = head[k]; i != -1; i = edge[i].next){ j = edge[i].v; if(dis[s][j]-edge[i].w>dis[s][k]){ dis[s][j] = edge[i].w + dis[s][k]; if(!vis[j]){ qeu[te++] = j; vis[j] = 1; } } }ts++; } } int main() { int i,j,k,u,v,w; while(scanf("%d %d",&n,&m)==2) { if(n+m==0)break; memset(head,-1,sizeof(head)); memset(belong,0,sizeof(belong)); memset(dfn,0,sizeof(dfn)); memset(vis,0,sizeof(vis)); ecnt = idx = cnt = 0; for(i = 0; i < m; ++ i) { scanf("%d %d %d",&u,&v,&w); add(u,v,w); } for(i = 1; i <= n; ++ i) if(!dfn[i]) tarjan(i); k = ecnt; ecnt = 0; memset(head,-1,sizeof(head)); memset(in,0,sizeof(in)); for(i = 0; i < k; ++ i) { u = belong[edge[i].u]; v = belong[edge[i].v]; if(v!=u){add(u,v,edge[i].w); in[v]++; } } for(i = 1; i <= cnt; ++ i) for(j = 1; j <= cnt; ++ j) if(i!=j) dis[i][j] = inf; else dis[i][j] = 0; for(i = 1; i <= cnt; ++ i) spfa(i); scanf("%d",&k); for(i = 0; i < k; ++ i) { scanf("%d %d",&u,&v); u = belong[u]; v = belong[v]; if(dis[u][v]!=inf)printf("%d\n",dis[u][v]); else puts("Nao e possivel entregar a carta"); } puts(""); } return 0; }

浙公网安备 33010602011771号