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;
}

posted on 2012-06-28 13:13  aigoruan  阅读(141)  评论(0)    收藏  举报

导航