POJ 3114 Countries in War(强连通分量+最短路)

题目大意:

n个间谍 他们之间传送信息需要一定的时间一个联通分量里面的间谍属于一个国家,之间的信息传递不需要时间然后问你从一个间谍传一个信息到另一个间谍那需要最少时间 也可能传不到

思路:先缩点,再最短路,由于n最大只有500.可以用邻接矩阵,而且对缩点后的DAG的边权可以做贪心处理,只留两个强连通分量间的最短边长即可。

//2852K	297MS	C++	2595B
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;

#define min(a,b) (a<b? a:b);
const int N = 555;
const int inf = 0x3f3f3f3f;
int n,m,sccnum;
int mp[N][N];
int head[N];
int col[N];
struct Edge
{
    int v,w,next;
}es[N*N];
int index;
int dfn[N],low[N];
int tmp[N],sta[N],top;
void tarjan(int u)
{
    dfn[u]=low[u]=++index;
    tmp[u]=1;
    sta[++top]=u;
    for(int i=head[u];~i;i=es[i].next)
    {
        int v=es[i].v;
        if(tmp[v]==0) tarjan(v);
        if(tmp[v]==1) low[u]=min(low[u],low[v]);
    }
    if(low[u]==dfn[u])
    {
        sccnum++;
        while(1)
        {
            int v=sta[top];
            col[v]=sccnum;
            tmp[v]=2;
            if(sta[top--]==u) break;
        }
    }
}

bool vis[N];
int dis[N];
void dijkstra(int src,int n)
{
    for(int i=1;i<=n;i++)
        dis[i]=inf,vis[i]=0;
    dis[src]=0;
    while(true)
    {

        int v=-1;
        for(int i=1;i<=n;i++)
            if(vis[i]==0&&(v==-1||dis[i]<dis[v])) v=i;
        if(v==-1) break;
        vis[v]=1;
        for(int i=1;i<=n;i++)
            if(mp[v][i]!=inf) dis[i]=min(dis[i],dis[v]+mp[v][i]);
    }
}
void ini()
{
    memset(head,-1,sizeof(head));
    memset(tmp,0,sizeof(tmp));
    memset(dfn,0,sizeof(dfn));
    memset(col,0,sizeof(col));
    sccnum=top=index=0;
}
int main()
{
    int cas=0;
    while(scanf("%d%d",&n,&m),n)
    {
        if(cas!=0) puts("");
        cas++;
        ini();
        for(int i=1;i<=m;i++)
        {
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            es[i].v=v;
            es[i].w=w;
            es[i].next=head[u];
            head[u]=i;
        }

        for(int i=1;i<=n;i++) if(dfn[i]==0) tarjan(i);
        memset(mp,0x3f,sizeof(mp));

        for(int u=1;u<=n;u++)
            for(int i=head[u];~i;i=es[i].next)
            {
                int v=es[i].v,w=es[i].w;
                if(col[v]==col[u]) continue;
                mp[col[u]][col[v]]=min(mp[col[u]][col[v]],w);
            }

        int op;
        scanf("%d",&op);
        while(op--)
        {
            int s,g;
            scanf("%d%d",&s,&g);
            if(col[s]==col[g]) puts("0");
            else
            {
                dijkstra(col[s],sccnum);
                if(dis[col[g]]==inf) puts("Nao e possivel entregar a carta");
                else printf("%d\n",dis[col[g]]);
            }
        }
    }
    return 0;

}
时间: 2024-12-09 08:20:09

POJ 3114 Countries in War(强连通分量+最短路)的相关文章

POJ 3114 - Countries in War(强连通分量+缩点+拓扑排序+DAG最短路)

Countries in War Time Limit:1000MS    Memory Limit:65536KB    64bit IO Format:%I64d & %I64u Appoint description: Description In the year 2050, after different attempts of the UN to maintain peace in the world, the third world war broke out. The impor

POJ 3114 Countries in War 强连通+最短路

用floyd超时了...注定的事情...题意:看案例就跑出来了..不需要看题了把.. #include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #include<vector> const int INF =1999299; int minn(int a,int b) { return a>b?b:a; } #define N 510 #define M

POJ 3114 Countries in War(强连通+最短路)

POJ 3114 Countries in War 题目链接 题意:给定一个有向图,强连通分支内传送不需要花费,其他有一定花费,每次询问两点的最小花费 思路:强连通缩点后求最短路即可 代码: #include <cstdio> #include <cstring> #include <vector> #include <queue> #include <stack> #include <algorithm> using namespa

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 #inc

POJ3114 Countries in War (强连通分量 + 缩点 + 最短路径 + 好题)

题目链接 题意是说在几个邮局之间传送一份信件,如果出发点和终止点在同一个国家传递,则时间为0,否则让你求花费最少时间,如果不能传到,则输出Nao e possivel entregar a carta.判断邮局是否在同一个国家的依据是发出的信件可以相互到达. 如果直接求最短路则无法判断两个邮局是否在同一个国家,判断两个邮局是否属于同一个国家的标志是在这个国家邮局间可以相互到达,那么这就是强连通了,所以要先缩点判读邮局是否在同一个国家,如果不是,则重新建图,建图的时候要维护好边权,求出最短边权,在

Poj 1904 King&#39;s Quest 强连通分量

题目链接: http://poj.org/problem?id=1904 题意: 有n个王子和n个公主,王子只能娶自己心仪的公主(一个王子可能会有多个心仪的公主),现已给出一个完美匹配,问每个王子都可以取哪些公主,并且保证取了一个公主后,全局还是存在完美匹配. 题解: 1.建图: 如果王子u对公主v心仪,则连一条边u->v.在样例给出的那组完美匹配中,如果王子u娶了公主v,连一条边v->u. 2.求强连通分量: 如果王子和自己心仪的公主属于同一个强连通分量,那么王子就可以娶这个公主. 1 #i

POJ - 1904 King&#39;s Quest(强连通分量+二分图匹配)

题目大意:有N个帅哥和N个美女,现在给出每个帅哥所喜欢的美女的编号,和一个帅哥和美女的完美匹配 问每个帅哥可以娶多少个美女,且当他娶完这个美女后,剩下的人还可以完美匹配 解题思路:神题啊,给一个大神的详细解答 具体是这样的,首先先建边,把帅哥和能娶到的美女连边,再把完美匹配的美女和帅哥连边,这样就形成了一张有向图了 接着,找出这张有向图的所有强连通分量,在强连通分量里面的帅哥都可以娶到自己喜欢的美女,且娶完这个美女后,不会影响到其他人 为什么呢? 假设xi为帅哥,yi和yj为美女,假设给定的完美

POJ 1904 King&#39;s Quest 强连通分量+二分图增广判定

http://www.cnblogs.com/zxndgv/archive/2011/08/06/2129333.html 这位神说的很好 #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <string> #include <stack> #include <ve

POJ 1904 King&#39;s Quest强连通分量+二分图完美匹配

题目描述: Description Once upon a time there lived a king and he had N sons. And there were N beautiful girls in the kingdom and the king knew about each of his sons which of those girls he did like. The sons of the king were young and light-headed, so i