A new Graph Game

来源:互联网 发布:数据分析软件有哪些 编辑:程序博客网 时间:2024/05/16 05:20

点击打开链接

题意:给你一张N个节点的无向图,然后给出M条边,给出第 I 条边到第J条边的距离。然后问你是否存在子环,如果存在,则输出最成环的最短距离和

解析:构图:选定源点及汇点,然后将源点至个点流量置为1,花费置为0.然后使用最小费用流,当返回值流量和,即flow < n 时,则输出NO,因为所有边成环最少边数为N。

其余和tour一样求法,处理一下某两点距离为最短距离即可。

#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;elsereturn true;}struct node{int f, c;};//node a;node 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;}node ans;ans.f = flow;ans.c = cost;return ans;}#define INF 0xfffffffint mapp[ maxn ][ maxn ];int main(){int Case;int n, m;scanf( "%d", &Case );for( int k = 1; k <= Case; ++k ){scanf( "%d%d", &n, &m );for( int i = 0; i <= n; ++i ){for( int j = 0; j <= n; ++j ){mapp[ i ][ j ] = INF;}}int start = 0, end = 2 * n + 1, N = 2 * n + 2;init( N );int x, y, value;for( int i = 1; i <= n; ++i ){addedge( 0, i, 1, 0 );addedge( n + i, end, 1, 0 );}int Max = 0;for( int i = 0; i < m; ++i ){scanf( "%d%d%d", &x, &y, &value );int temp = max( x, y );if( Max < temp ){Max = temp;}if( mapp[ x ][ y ] > value ){mapp[ x ][ y ] = mapp[ y ][ x ] = value;}}for( int i = 1; i <= n ; ++i ){for( int j = 1; j <= n; ++j ){if( mapp[ i ][ j ] != INF ){addedge( i, n + j, 1, mapp[ i ][ j ] );}}}int cost;node ans = minCostMaxflow( start, end, cost );printf( "Case %d: ", k );if( ans.f >= n ){printf( "%d\n", ans.c );}else{puts( "NO" );}} return 0;}


0 0