首页 > 代码库 > POJ 3114 Countries in War(强联通分量+Tarjan)

POJ 3114 Countries in War(强联通分量+Tarjan)

题目链接

题意 : 给你两个城市让你求最短距离,如果两个城市位于同一强连通分量中那距离为0.

思路 :强连通分量缩点之后,求最短路。以前写过,总感觉记忆不深,这次自己敲完再写了一遍。

  1 #include <cstdio>  2 #include <cstring>  3 #include <iostream>  4 #include <vector>  5 #include <stack>  6 #include <queue>  7 #include <algorithm>  8 #define maxn 505  9 using namespace std ; 10  11 struct node 12 { 13     int u,v,w,next ; 14 } edge[maxn*maxn]; 15 int p[maxn][maxn]; 16 int dfn[maxn],low[maxn],head[maxn] ,vis[maxn],dis[maxn],belong[maxn]; 17 int timee,cnt ,cntt,n,m; 18 stack<int>stk ; 19  20 void Init() 21 { 22     timee = 0 ; 23     cnt = cntt = 0 ; 24     memset(dfn,0,sizeof(dfn)) ; 25     memset(low,0,sizeof(low)) ; 26     memset(dis,0,sizeof(dis)) ; 27     memset(head,-1,sizeof(head)) ; 28     memset(vis,0,sizeof(vis)) ; 29     memset(p,0x3f,sizeof(p)) ; 30 } 31 void addedge(int u,int v,int w) 32 { 33     edge[cnt].u = u ; 34     edge[cnt].v = v ; 35     edge[cnt].w = w ; 36     edge[cnt].next = head[u] ; 37     head[u] = cnt++ ; 38 } 39 void tarjan(int u) 40 { 41     //cout<<u<<endl; 42     int v ; 43     vis[u] = 1 ; 44     dfn[u] = low[u] = ++ timee ; 45     stk.push(u) ; 46     for(int i = head[u] ; i != -1 ; i = edge[i].next) 47     { 48         v = edge[i].v ; 49         if(!dfn[v]) 50         { 51             //printf("v = %d\n",v) ; 52             tarjan(v) ; 53             low[u] = min(low[v],low[u]) ; 54         } 55         else if(vis[v]) 56             low[u] = min(low[u],dfn[v]) ; 57     } 58     if(low[u] == dfn[u]) 59     { 60         cntt ++ ; 61         do 62         { 63             v = stk.top() ; 64             stk.pop() ; 65             vis[v] = 0 ; 66             belong [v] = cntt ; 67          //   puts("1") ; 68         } 69         while(v != u) ; 70     } 71 } 72 void SPFA(int u,int v) 73 { 74     queue<int>Q ; 75     for(int i = 1 ; i <= cntt ; i++) 76     { 77         dis[i] = 999999999 ; 78         vis[i] = 0 ; 79     } 80     dis[u] = 0; 81     vis[u] = 1; 82     Q.push(u) ; 83     while(!Q.empty()) 84     { 85         int s = Q.front() ; 86         Q.pop() ; 87         vis[s] = 0 ; 88         for(int i = 1 ; i <= n ; i ++ ) 89         { 90             if(p[s][i] != 999999999) 91             { 92                 if(dis[i] > dis[s] + p[s][i]) 93                 { 94                     dis[i] = dis[s] + p[s][i] ; 95                     if(!vis[i]) 96                     { 97                         Q.push(i) ; 98                         vis[i] = 1 ; 99                     }100                 }101             }102         }103     }104     if(dis[v] != 999999999)105         printf("%d\n",dis[v]) ;106     else printf("Nao e possivel entregar a carta\n") ;107 }108 void rebuild()109 {110     for(int i = 1 ; i <= n ; i++)111     {112         for(int j = head[i] ; j != -1 ; j = edge[j].next)113         {114          //   int s = edge[i].v ;115             int v = belong[edge[j].v] ;116             int u = belong[edge[j].u] ;117             if(u != v)118                 p[u][v] = min(p[u][v],edge[j].w) ;119         }120     }121     for(int i = 1 ; i <= cntt ; i++)122         p[i][i] = 0 ;123 }124 int main()125 {126     int x,y,h,k;127     while(~scanf("%d %d",&n,&m))128     {129         if(n == 0 && m == 0) break ;130         Init() ;131         for(int i = 0 ; i < m ; i++)132         {133             scanf("%d %d %d",&x,&y,&h) ;134             addedge(x,y,h) ;135         }136         for(int i = 1 ; i <= n ; i++)137         {138             if(!dfn[i])139                 tarjan(i) ;140         }141        // cout<<"s"<<endl;142         rebuild() ;143        // cout<<"s"<<endl;144         scanf("%d",&k) ;145         for(int i = 0 ; i < k ; i++)146         {147             //cout<<i<<endl;148             scanf("%d %d",&x,&y) ;149             SPFA(belong[x],belong[y]) ;150         }151         printf("\n") ;152     }153     return 0 ;154 }
View Code

 

POJ 3114 Countries in War(强联通分量+Tarjan)