HDU 1853 Cyclic Tour

题意:Little Tom要“环”游一些城市,每个城市只能游玩一次。现在给出一张有向图和每条边的费用。求最小费用。

要走环,很容易想到二分图匹配。这里还是一样的,拆点。把每个点拆开,变成i,i',分别和源点S汇点T相连,费用是0,容量是1。然后对原图中的每条边(u,v),对应边(u,v',1,cost),跑费用流,如果最大流=城市数,说明存在一个方案,答案就是最小费用流算出来的费用。

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <cstring>
 4 #include <queue>
 5 #define maxn 210
 6 #define maxm 100000
 7 #define INF 1<<30
 8 using namespace std;
 9 struct MCMF{
10     int src,sink,e,n;
11     int first[maxn];
12     int cap[maxm],cost[maxm],v[maxm],next[maxm];
13     void init(){
14         e = 0;
15         memset(first,-1,sizeof(first));
16     }
17     void add_edge(int a,int b,int cc,int ww){
18         v[e] = b;next[e] = first[a];cap[e] = cc;
19         cost[e] = ww;first[a] = e++;
20         v[e] = a;next[e] = first[b];cap[e] = 0;
21         cost[e] = -ww;first[b] = e++;
22     }
23 
24     int d[maxn],pre[maxn],pos[maxn];
25     bool vis[maxn];
26 
27     bool spfa(int s,int t){
28         memset(pre,-1,sizeof(pre));
29         memset(vis,0,sizeof(vis));
30         queue<int> Q;
31         for(int i = 0;i <= n;i++)   d[i] = INF;
32         Q.push(s);pre[s] = s;d[s] = 0;vis[s] = 1;
33         while(!Q.empty()){
34             int u = Q.front();Q.pop();
35             vis[u] = 0;
36             for(int i = first[u];i != -1;i = next[i]){
37                 if(cap[i] > 0 && d[u] + cost[i] < d[v[i]]){
38                     d[v[i]] = d[u] + cost[i];
39                     pre[v[i]] = u;pos[v[i]] = i;
40                     if(!vis[v[i]])  vis[v[i]] = 1,Q.push(v[i]);
41                 }
42             }
43         }
44         return pre[t] != -1;
45     }
46 
47     int Mincost,Maxflow;
48     int MincostFlow(int s,int t,int nn){
49         Mincost = Maxflow = 0,n = nn;
50         while(spfa(s,t)){
51             int min_f = INF;
52             for(int i = t;i != s;i = pre[i])
53                 if(cap[pos[i]] < min_f) min_f = cap[pos[i]];
54             Mincost += d[t] * min_f;
55             Maxflow += min_f;
56             for(int i = t;i != s;i = pre[i]){
57                 cap[pos[i]] -= min_f;
58                 cap[pos[i]^1] += min_f;
59             }
60         }
61         return Mincost;
62     }
63 };
64 MCMF g;
65 
66 int main()
67 {
68     int n,m;
69     while(scanf("%d%d",&n,&m) == 2){
70         g.init();
71         int S = 0,T = 2*n+1;
72         for(int i = 1;i <= n;i++){
73             g.add_edge(S,i,1,0);
74             g.add_edge(i+n,T,1,0);
75         }
76         for(int i = 1;i <= m;i++){
77             int a,b,c;
78             scanf("%d%d%d",&a,&b,&c);
79             g.add_edge(a,b+n,1,c);
80         }
81         int ans = g.MincostFlow(S,T,T);
82         if(g.Maxflow == n)  printf("%d
",ans);
83         else printf("-1
");
84     }
85     return 0;
86 }
View Code
原文地址:https://www.cnblogs.com/zhexipinnong/p/3422817.html