HDU Intelligence System(tarjan+缩点)
http://acm.hdu.edu.cn/showproblem.php?pid=3072
最近为了CF上的一道题,又把强连通分支的tarjan算法看了一遍,为了加深印象,就做了HDU上的这题。。。。
题意:有一个情报系统,要从0开始传播一个情报,如果两个人可以互达那么两人之间的传播费用为0 ,否则两人之间的传播费用为ci,求要情报传达到每个人的最小费用。
思路:既然一个强连通分支内的传播费用为0,求图中有几个强连通分支,缩点后求各点之间的最小费用。
代码:
View Code
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <iostream> #include <algorithm> #include <stack> #define N 100005 #define M 50005 using namespace std ; const int INF = ( 1 << 30 ); struct node { int e , len ; int next ; }p[N] ; int head[M] , n , m , num , cnt , id ; bool used[M] , vist[M] ;//used[i]表示点i是否遍历过,vist[i]表示点i是否在栈里; int dis[M] , dfn[M] , low[M] , belong[M] ; stack<int>q ; //初始化 void init() { num = cnt = id = 0 ; for ( int i = 0 ; i <= n ; i++ ) { dfn[i] = low[i] = 0 ; used[i] = vist[i] = false ; dis[i] = INF ; head[i] = -1 ; } while ( !q.empty()) q.top(); } void add ( int x , int y , int z ) { p[num].e = y ; p[num].len = z ; p[num].next = head[x]; head[x] = num++ ; } void tarjan( int x ) { int i , v ; dfn[x] = low[x] = ++id ; used[x] = vist[x] = true ; q.push( x ) ; for ( i = head[x] ; i != -1 ; i = p[i].next ) { v = p[i].e ; if( !used[v] ) { tarjan( v ) ; low[x] = min( low[x] , low[v] ); } else if( vist[v] ) { low[x] = min( low[x] , dfn[v] ); } } if ( dfn[x] == low[x] ) { cnt++ ; do { v = q.top(); q.pop(); belong[v] = cnt ; vist[v] = false ; }while( v != x ) ; } } int main() { int i , j , x , y , z ; while ( scanf ( "%d%d" , &n , &m ) != EOF ) { init(); for ( i = 1 ; i <= m ; i++ ) { scanf ( "%d%d%d" , &x , &y , &z ); //x++ ; y++ ; add ( ++x , ++y , z ) ; } for ( i = 1 ; i <= n ; i++ ) if ( !dfn[i] ) tarjan( i ) ; for ( i = 1 ; i <= n ; i++ ) { for ( j = head[i] ; j != -1 ; j = p[j].next ) { z = p[j].e ; x = belong[i]; y = belong[z] ; if ( x != y ) dis[y] = min( dis[y] , p[j].len ) ; } } int sum = 0 ; for ( i = 1 ; i <= n ; i++ ) if ( dis[i] < INF ) sum += dis[i] ; printf ( "%d\n" , sum ) ; } return 0 ; }