标签:最小费用最大流
题意:在一个王国有N个城市,M条路。选择N条路,构成一个环路。求出最小距离。
解析:构图,最小费用最大流。将源点和终点至个点花费记作0,然后将所有路径流量记作1或同一值。
#include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; const int maxn = 10000; const int maxm = 100000; const int INF = 0xfffffff; struct Edge{ int to, next, cap, flow, cost; }edge[ maxm ]; int head[ maxn ], tol; int pre[ maxn ], dis[ maxn ]; bool vis[ maxn ]; int N; void init( int n ){ N = n; tol = 0; memset( head, -1, sizeof( head ) ); } void addedge( int u, int v, int cap, int cost ){ edge[ tol ].to = v; edge[ tol ].cap = cap; edge[ tol ].cost = cost; edge[ tol ].flow = 0; edge[ tol ].next = head[ u ]; head[ u ] = tol++; edge[ tol ].to = u; edge[ tol ].cap = 0; edge[ tol ].cost = -cost; edge[ tol ].flow = 0; edge[ tol ].next = head[ v ]; head[ v ] = tol++; } bool spfa( int s, int t ){ queue< int > q; for( int i = 0; i < N; ++i ){ dis[ i ] = INF; vis[ i ] = false; pre[ i ] = -1; } dis[ s ] = 0; vis[ s ] = true; q.push( s ); while( !q.empty( ) ){ int u = q.front(); q.pop(); vis[ u ] = false; for( int i = head[ u ]; i != - 1; i = edge[ i ].next ){ int v = edge[ i ].to; if( edge[ i ].cap > edge[ i ].flow && dis[ v ] > dis[ u ] + edge[ i ].cost ){ dis[ v ] = dis[ u ] + edge[ i ].cost; pre[ v ] = i; if( !vis[ v ] ){ vis[ v ] = true; q.push( v ); } } } } if( pre[ t ] == -1 ) return false; else return true; } int minCostMaxflow( int s, int t, int &cost ){ int flow = 0; cost = 0; while( spfa( s, t ) ){ int Min = INF; for( int i = pre[ t ]; i != - 1; i = pre[ edge[ i ^ 1 ].to ] ){ if( Min > edge[ i ].cap - edge[ i ].flow ) Min = edge[ i ].cap - edge[ i ].flow; } for( int i = pre[ t ]; i != -1; i = pre[ edge[ i ^ 1 ].to ] ){ edge[ i ].flow += Min; edge[ i ^ 1 ].flow -= Min; cost += edge[ i ].cost * Min; } flow += Min; } return cost; } int main(){ int Case; int n, m; scanf( "%d", &Case ); while( Case-- ){ scanf( "%d%d", &n, &m ); int N = 2 * n + 2; int start = 0, end = 2 * n + 1; init( N ); for( int i = 1; i <= n; ++ i ){ addedge( 0, i, 1, 0 ); } for( int i = 1; i <= n; ++i ){ addedge( n + i, end, 1, 0 ); } int x, y, value; for( int i = 0; i < m; ++i ){ scanf( "%d%d%d", &x, &y, &value ); addedge( x, n + y, 1, value ); } int cost; int ans = minCostMaxflow( start, end, cost ); cout << ans << endl; } return 0; }
标签:最小费用最大流
原文地址:http://blog.csdn.net/bo_jwolf/article/details/38022447