码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2015-05-16 18:21:21      阅读:420      评论:0      收藏:0      [点我收藏+]

标签:

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


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

标签:

原文地址:http://blog.csdn.net/winddreams/article/details/45770027

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!