poj3114--Countries in War(强连通缩点+spfa)

poj3114:题目链接

.题目大意:给出n个城市,m条送信的渠道,u v w代表u城市送信到v城市需要w小时。同时如果两个城市属于一个国家,那么送信时间为0,在一个国家中的条件是所有城市相互之间可以送信到达。

强连通找出连通块,那么每个连通块就是一个国家,缩点,重新建图,spfa找出要求的最短路径

#include <cstdio>
#include <cstring>
#include <stack>
#include <queue>
#include <algorithm>
using namespace std ;
#define INF 0x3f3f3f3f
struct node{
    int u , v , w ;
    int next ;
}edge[500000] , tree[500000];
int head[510] , h_tree[510] , cnt ;
int low[510] , dnf[510] , time ;
int belong[510] , vis[510] , dis[510] , num ;
queue <int> que ;
stack <int> sta ;
void init() {
    cnt = time = num = 0 ;
    memset(head,-1,sizeof(head)) ;
    memset(h_tree,-1,sizeof(head)) ;
    memset(low,0,sizeof(low)) ;
    memset(dnf,0,sizeof(dnf)) ;
    memset(belong,0,sizeof(belong)) ;
    memset(vis,0,sizeof(vis)) ;
}
void add(int u,int v,int w) {
    edge[cnt].u = u ; edge[cnt].v = v ; edge[cnt].w = w ;
    edge[cnt].next = head[u] ; head[u] = cnt++ ;
}
void add_tree(int u,int v,int w) {
    tree[cnt].u = u ; tree[cnt].v = v ; tree[cnt].w = w ;
    tree[cnt].next = h_tree[u] ; h_tree[u] = cnt++ ;
}
void tarjan(int u) {
    dnf[u] = low[u] = ++time ;
    vis[u] = 1 ;
    sta.push(u) ;
    int i , v ;
    for(i = head[u] ; i != -1 ; i = edge[i].next) {
        v = edge[i].v ;
        if( !dnf[v] ) {
            tarjan(v) ;
            low[u] = min(low[v],low[u]) ;
        }
        else if( vis[v] )
            low[u] = min(low[u],dnf[v]) ;
    }
    if( low[u] == dnf[u] ) {
        ++num ;
        while( 1 ) {
            i = sta.top() ;
            sta.pop() ;
            vis[i] = 0 ;
            belong[i] = num ;
            if( i == u ) break ;
        }
    }
}
int spfa(int u,int s) {
    while( !que.empty() ) que.pop() ;
    memset(vis,0,sizeof(vis)) ;
    memset(dis,INF,sizeof(dis)) ;
    vis[u] = 1 ;
    dis[u] = 0 ;
    que.push(u) ;
    int i , v ;
    while( !que.empty() ) {
        u = que.front() ;
        que.pop() ;
        vis[u] = 0 ;
        for(i = h_tree[u] ; i != -1 ; i = tree[i].next) {
            v = tree[i].v ;
            if( dis[v] > dis[u] + tree[i].w ) {
                dis[v] = dis[u] + tree[i].w ;
                if( !vis[v] ) {
                    vis[v] = 1 ;
                    que.push(v) ;
                }
            }
        }
    }
    return dis[s] ;
}
int main() {
    int n , m  , q ;
    int u , v , w , i , j ;
    while( scanf("%d %d", &n, &m) && n+m > 0 ) {
        init() ;
        while( m-- ) {
            scanf("%d %d %d", &u, &v, &w) ;
            add(u,v,w) ;
        }
        for(i = 1 ; i <= n ; i++)
            if( !dnf[i] ) tarjan(i) ;
        for(i = 1 , cnt = 0 ; i <= n ; i++) {
            for(j = head[i] ; j != -1 ; j = edge[j].next) {
                u = belong[ edge[j].u ] ;
                v = belong[ edge[j].v ] ;
                w = edge[j].w ;
                if( u != v )
                    add_tree(u,v,w) ;
            }
        }
        scanf("%d", &q) ;
        while( q-- ) {
            scanf("%d %d", &u, &v) ;
            u = belong[u] ;
            v = belong[v] ;
            w = spfa(u,v) ;
            if( w == INF )
                printf("Nao e possivel entregar a carta\n") ;
            else
                printf("%d\n", w) ;
        }
        printf("\n") ;
    }
    return 0 ;
}
时间: 2024-08-19 14:01:24

poj3114--Countries in War(强连通缩点+spfa)的相关文章

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

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

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(强连通分量+缩点+拓扑排序+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

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

题目链接: http://poj.org/problem?id=3114 题目大意: 间谍在战争期间想要传递一份谍报回国,谍报可以在邮局之间传递,但这种传递是单向的, 并且会小号一些时间.但是如果两个邮局在同一个国家的话,那么谍报在这两个邮局之间传 递是不消耗时间的,可以立即到达.如果几个邮局发出的谍报可以通过一些路径相互到达, 那么这些邮局就属于一个国家.那么问题来了:给出一个起点和终点,问最快什么时候能够 将谍报传递到. 思路: 本题求得是有向图上的最短路.以邮局为点,从一个邮局到达另一个邮

poj3592--Instantaneous Transference(强连通缩点+spfa)

poj3592:题目链接 题目大意:给出n*m的矩阵,其中数字代表矿物的数量,#代表不可达,*代表传送门,传送到给定的位置.问最多可以收集多少矿物(每个矿物只能被收集一次,可以经过多次) 因为存在传送门,所以就会形成环,用强连通将形成环的缩成一个点,记录每个点代表的矿物数,最后用spfa找出最长路,也就是可以得到的最多的矿物数.(不会出现矩阵外的点) #include <cstdio> #include <cstring> #include <stack> #inclu

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

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

[BZOJ 1179]ATM题解 Tarjan缩点+SPFA

[BZOJ 1179]ATM题解 Tarjan缩点+SPFA Description Input 第一行包含两个整数N.M.N表示路口的个数,M表示道路条数.接下来M行,每行两个整数,这两个整数都在1到N之间,第i+1行的两个整数表示第i条道路的起点和终点的路口编号.接下来N行,每行一个整数,按顺序表示每个路口处的ATM机中的钱数.接下来一行包含两个整数S.P,S表示市中心的编号,也就是出发的路口.P表示酒吧数目.接下来的一行中有P个整数,表示P个有酒吧的路口的编号 Output 输出一个整数,

Light OJ 1168 Wishing Snake 强连通缩点+哈密顿通路

题目来源:Light OJ 1168 Wishing Snake 题意:有点难看懂题意 看了一个小时再加别人的代码才懂意思 从0开始 输入的那些每一对u v 都要经过 就是从0到到达那些点 思路:首先缩点 每一个强连通分量里面的点都是可达的 缩点后的图是有向无环图 如果从0这个强连通分量可以出去到2个强连通分量 那么这两个强连通分量是不可能相互可达 所以可行的方案就是所有的强连通分量连成一线 一个一个串起来 除了第一个 出度是1入度是0和最后一个出度是0入度是1 其他都是入度等于出度是1 特判只

强连通缩点— HDU1827

强连通缩点以后最终形成的是一棵树 我们可以根据树的性质来看缩点以后的强连通分量图,就很好理解了 /* gyt Live up to every day */ #include<cstdio> #include<cmath> #include<iostream> #include<algorithm> #include<vector> #include<stack> #include<cstring> #include<