传送门:【SGU】252 Railway Communication
题目分析:源点向所有点建边(s,i,1,0),所有点向汇点建边(i+n,t,1,0),所有边建边(u,v+n,1,w),跑一遍最小费用最大流即可。
代码如下:
#include <cmath> #include <cstdio> #include <cstring> #include <algorithm> using namespace std ; typedef long long LL ; #define REP( i , a , b ) for ( int i = a ; i < b ; ++ i ) #define REV( i , a , b ) for ( int i = a ; i >= b ; -- i ) #define FOR( i , a , b ) for ( int i = a ; i <= b ; ++ i ) #define CLR( a , x ) memset ( a , x , sizeof a ) #define CPY( a , x ) memcpy ( a , x , sizeof a ) const int MAXN = 205 ; const int MAXE = 3005 ; const int INF = 0x3f3f3f3f ; struct Edge { int v , c , w , n ; Edge () {} Edge ( int v , int c , int w , int n ) : v ( v ) , c ( c ) , w ( w ) , n ( n ) {} } E[MAXE] ; int H[MAXN] , cntE ; int d[MAXN] , cur[MAXN] , cap[MAXN] ; int Q[MAXN] , head , tail ; bool vis[MAXN] ; int s , t ; int flow ; int cost ; int n , m ; int S[MAXN] , top ; void clear () { cntE = 0 ; CLR ( H , -1 ) ; } void addedge ( int u , int v , int c , int w ) { E[cntE] = Edge ( v , c , w , H[u] ) ; H[u] = cntE ++ ; E[cntE] = Edge ( u , 0 , -w , H[v] ) ; H[v] = cntE ++ ; } int spfa () { CLR ( d , INF ) ; CLR ( vis , 0 ) ; head = tail = 0 ; Q[tail ++] = s ; cap[s] = INF ; cur[s] = -1 ; d[s] = 0 ; while ( head != tail ) { int u = Q[head ++] ; if ( head == MAXN ) head = 0 ; vis[u] = 0 ; for ( int i = H[u] ; ~i ; i = E[i].n ) { int v = E[i].v , c = E[i].c , w = E[i].w ; if ( c && d[v] > d[u] + w ) { d[v] = d[u] + w ; cap[v] = min ( cap[u] , c ) ; cur[v] = i ; if ( !vis[v] ) { vis[v] = 1 ; Q[tail ++] = v ; if ( tail == MAXN ) tail = 0 ; } } } } if ( d[t] == INF ) return 0 ; cost += d[t] * cap[t] ; flow += cap[t] ; for ( int i = cur[t] ; ~i ; i = cur[E[i ^ 1].v] ) { E[i].c -= cap[t] ; E[i ^ 1].c += cap[t] ; } return 1 ; } int mcmf () { flow = cost = 0 ; while ( spfa () ) ; return cost ; } void dfs ( int u ) { S[top ++] = u ; for ( int i = H[u] ; ~i ; i = E[i].n ) { int v = E[i].v ; if ( v == s || v == t || E[i].c ) continue ; dfs ( v - n ) ; break ; } } void solve () { int u , v , w ; clear () ; s = 0 ; t = n << 1 | 1 ; FOR ( i , 1 , n ) { addedge ( s , i , 1 , 0 ) ; addedge ( i + n , t , 1 , 0 ) ; } REP ( i , 0 , m ) { scanf ( "%d%d%d" , &u , &v , &w ) ; addedge ( u , v + n , 1 , w ) ; } mcmf () ; printf ( "%d %d\n" , n - flow , cost ) ; for ( int i = H[t] ; ~i ; i = E[i].n ) if ( !E[i].c ) { top = 0 ; dfs ( E[i].v - n ) ; printf ( "%d" , top ) ; REP ( j , 0 , top ) printf ( " %d" , S[j] ) ; printf ( "\n" ) ; } } int main () { while ( ~scanf ( "%d%d" , &n , &m ) ) solve () ; return 0 ; }