POJ3114 Countries in War【强连通分量】【最短路径】

来源:互联网 发布:新浪微博淘宝版入口 编辑:程序博客网 时间:2024/06/06 07:53

题目链接:

http://poj.org/problem?id=3114


题目大意:

间谍在战争期间想要传递一份谍报回国,谍报可以在邮局之间传递,但这种传递是单向的,

并且会小号一些时间。但是如果两个邮局在同一个国家的话,那么谍报在这两个邮局之间传

递是不消耗时间的,可以立即到达。如果几个邮局发出的谍报可以通过一些路径相互到达,

那么这些邮局就属于一个国家。那么问题来了:给出一个起点和终点,问最快什么时候能够

将谍报传递到。


思路:

本题求得是有向图上的最短路。以邮局为点,从一个邮局到达另一个邮局的时间为边权,但是

这里的边权分两组:相同国家的邮局之间的边权和不同国家的邮局之间的边权。考虑到相同国

家之间的邮局直接可以相互到达。所以想到了强连通分量。可以相互达到的邮局其实就是一个

强连通分量,将原图进行缩点。那么一个强连通分量就是一个国家。

进行缩点之后,原图就变成了一个有向无环图(DAG),重新建图,然后根据输入的起点和终点,

对新图用SPFA算法求最短路径。这道题和POJ3592一样,详细参考博文:

http://blog.csdn.net/lianai911/article/details/43738299


AC代码:

#include<iostream>#include<algorithm>#include<cstdio>#include<cstring>#include<queue>using namespace std;const int MAXN = 550;const int MAXM = MAXN*MAXN;const int INF = 0xffffff0;struct EdgeNode{    int to;    int w;    int next;}Edges[MAXM],Edges1[MAXM];int Head[MAXN],Head1[MAXN];int low[MAXN],dfn[MAXN],belong[MAXN];int vis[MAXN],vist[MAXN];int Stack[MAXN];int m,lay,scc,id,ip,N,M;int Dist[MAXN];void AddEdges(int u,int v,int w){    Edges[id].to = v;    Edges[id].w = w;    Edges[id].next = Head[u];    Head[u] = id++;}void AddEdges1(int u,int v,int w){    Edges1[ip].to = v;    Edges1[ip].w = w;    Edges1[ip].next = Head1[u];    Head1[u] = ip++;}int TarBFS(int pos){    int v;    vis[pos] = 1;    low[pos] = dfn[pos] = ++lay;    Stack[m++] = pos;    for(int i = Head[pos]; i != -1; i = Edges[i].next)    {        int v = Edges[i].to;        if( !dfn[v] )        {            TarBFS(v);            low[pos] = min(low[pos],low[v]);        }        else if(vis[v])            low[pos] = min(low[pos],low[v]);    }    if(dfn[pos] == low[pos])    {        ++scc;        do        {            v = Stack[--m];            belong[v] = scc;            vis[v] = 0;        }while(v != pos);    }    return 0;}void ReBuildMap(){    for(int u = 1; u <= N; ++u)    {        for(int k = Head[u]; k != -1; k = Edges[k].next)        {            int v = Edges[k].to;            if(belong[u] != belong[v])                AddEdges1(belong[u],belong[v],Edges[k].w);        }    }}void SPFA(int s){    memset(vist,0,sizeof(vist));    for(int i = 0; i <= N; ++i) //不能用memset(Dist,INF,sizeof(Dist));赋值        Dist[i] = INF;    queue<int> Q;    Q.push(s);    vist[s] = 1;    Dist[s] = 0;    while( !Q.empty() )    {        int u = Q.front();        Q.pop();        vist[u] = 0;        for(int i = Head1[u]; i != -1; i = Edges1[i].next)        {            int v = Edges1[i].to;            if(Dist[v] > Dist[u] + Edges1[i].w)            {                Dist[v] = Dist[u] + Edges1[i].w;                if( !vist[v] )                {                    vist[v] = 1;                    Q.push(v);                }            }        }    }}int main(){    int u,v,w,k;    while(~scanf("%d%d",&N,&M) && N)    {        memset(Head,-1,sizeof(Head));        memset(Head1,-1,sizeof(Head1));        memset(vis,0,sizeof(vis));        memset(low,0,sizeof(low));        memset(dfn,0,sizeof(dfn));        scc = m = lay = id = ip = 0;        for(int i = 0; i < M; ++i)        {            scanf("%d%d%d",&u,&v,&w);            AddEdges(u,v,w);        }        for(int i = 1; i <= N; ++i)        {            if(!dfn[i])                TarBFS(i);        }        ReBuildMap();        scanf("%d",&k);        while(k--)        {            scanf("%d%d",&u,&v);            if(belong[u]==belong[v])                printf("0\n");            else            {                SPFA(belong[u]);                if(Dist[belong[v]] != INF)                    printf("%d\n",Dist[belong[v]]);                else                    printf("Nao e possivel entregar a carta\n");            }        }        printf("\n");    }    return 0;}


0 0
原创粉丝点击