hdu 3488

 

题意:给出一个有向图,边带权,求一些环,使得每个点属于且仅属于一个环,幷最小化环边的权值和。

 

思想和最小路径覆盖是一样的,将每个定点拆成两个点,假设u拆成u1,u2,那么所有边(v,u)对应新图中的(v1,u2),(u,v)对应(u1,v2)。

然后会发现一种合法方案和新图(是一个二分图)的一个完美匹配一一对应。

然后就可以用KM或网络流解决了。

(这种有向图路径拆边的思想很漂亮)

 

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <queue>
 4 #include <vector>
 5 #define oo 0x3f3f3f3f
 6 #define maxn 410
 7 using namespace std;
 8 
 9 struct Edge {
10     int u, v, c, f;
11     Edge( int u, int v, int c, int f ):u(u),v(v),c(c),f(f){}
12 };
13 struct Mcmf {
14     int n, src, dst;
15     vector<Edge> edge;
16     vector<int> g[maxn];
17     int dis[maxn], ext[maxn], pth[maxn];
18 
19     void init( int nn, int s, int d ) {
20         n = nn;
21         src = s;
22         dst = d;
23         for( int i=1; i<=n; i++ )
24             g[i].clear();
25         edge.clear();
26     }
27     void add_edge( int u, int v, int c, int f ) {
28         g[u].push_back( edge.size() );
29         edge.push_back( Edge(u,v,c,f) );
30         g[v].push_back( edge.size() );
31         edge.push_back( Edge(v,u,-c,0) );
32     }
33     bool spfa( int &flow, int &cost ) {
34         queue<int> qu;
35         memset( dis, 0x3f, sizeof(dis) );
36         qu.push( src );
37         dis[src] = 0;
38         ext[src] = true;
39         pth[src] = -1;
40         while( !qu.empty() ) {
41             int u=qu.front();
42             qu.pop();
43             ext[u] = false;
44             for( int t=0; t<g[u].size(); t++ ) {
45                 Edge &e = edge[g[u][t]];
46                 if( e.f && dis[e.v]>dis[e.u]+e.c ) {
47                     dis[e.v] = dis[e.u]+e.c;
48                     pth[e.v] = g[u][t];
49                     if( !ext[e.v] ) {
50                         ext[e.v] = true;
51                         qu.push( e.v );
52                     }
53                 }
54             }
55         }
56         if( dis[dst]==oo ) return false;
57         int flw = oo;
58         for( int eid=pth[dst]; eid!=-1; eid=pth[edge[eid].u] ) 
59             flw = min( flw, edge[eid].f );
60         for( int eid=pth[dst]; eid!=-1; eid=pth[edge[eid].u] ) {
61             edge[eid].f -= flw;
62             edge[eid^1].f += flw;
63         }
64         flow += flw;
65         cost += flw*dis[dst];
66         return true;
67     }
68     void mcmf( int &flow, int &cost ) {
69         flow = cost = 0;
70         while( spfa(flow,cost) );
71     }
72 };
73 
74 int n, m;
75 Mcmf M;
76 
77 int main() {
78     int T;
79     scanf( "%d", &T );
80     while(T--) {
81         scanf( "%d%d", &n, &m );
82         int tot = n+n+2;
83         M.init( tot, tot-1, tot );
84         for( int i=1,u,v,w; i<=m; i++ ) {
85             scanf( "%d%d%d", &u, &v, &w );
86             M.add_edge( u, v+n, w, 1 );
87         }
88         for( int u=1; u<=n; u++ ) {
89             M.add_edge( M.src, u, 0, 1 );
90             M.add_edge( u+n, M.dst, 0, 1 );
91         }
92         int flow, cost;
93         M.mcmf(flow,cost);
94         printf( "%d\n", cost );
95     }
96 }
View Code

 

posted @ 2015-03-07 21:46  idy002  阅读(153)  评论(0编辑  收藏  举报