http://acm.hdu.edu.cn/showproblem.php?pid=3488
题意:
给出n个点和m条边,每条边有距离,把这n个点分成1个或多个环,且每个点只能在一个环中,保证有解。
思路:
把一个点分成两部分,1~n和n+i~2*n。
连边的情况是这样的,(src,i,1,0),(i+n,dst,1,0)。
如果两个点之间相同,则(i,j+n,1,d)。
其实这道题目就是选n条边,如何使得权值之和最小。
具体请参考这http://blog.csdn.net/u013480600/article/details/39185013
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<queue> 6 using namespace std; 7 typedef long long LL; 8 9 const int maxn=400+5; 10 const int INF=0x3f3f3f3f; 11 12 struct Edge 13 { 14 int from, to, cap, flow, cost; 15 Edge(int u, int v, int c, int f, int w) :from(u), to(v), cap(c), flow(f), cost(w) {} 16 }; 17 18 struct MCMF 19 { 20 int n, m; 21 vector<Edge> edges; 22 vector<int> G[maxn]; 23 int inq[maxn]; 24 int d[maxn]; 25 int p[maxn]; 26 int a[maxn]; 27 28 void init(int n) 29 { 30 this->n = n; 31 for (int i = 0; i<n; i++) G[i].clear(); 32 edges.clear(); 33 } 34 35 void AddEdge(int from, int to, int cap, int cost) 36 { 37 edges.push_back(Edge(from, to, cap, 0, cost)); 38 edges.push_back(Edge(to, from, 0, 0, -cost)); 39 m = edges.size(); 40 G[from].push_back(m - 2); 41 G[to].push_back(m - 1); 42 } 43 44 bool BellmanFord(int s, int t, int &flow, LL & cost) 45 { 46 for (int i = 0; i<n; i++) d[i] = INF; 47 memset(inq, 0, sizeof(inq)); 48 d[s] = 0; inq[s] = 1; p[s] = 0; a[s] = INF; 49 50 queue<int> Q; 51 Q.push(s); 52 while (!Q.empty()){ 53 int u = Q.front(); Q.pop(); 54 inq[u] = 0; 55 for (int i = 0; i<G[u].size(); i++){ 56 Edge& e = edges[G[u][i]]; 57 if (e.cap>e.flow && d[e.to]>d[u] + e.cost){ 58 d[e.to] = d[u] + e.cost; 59 p[e.to] = G[u][i]; 60 a[e.to] = min(a[u], e.cap - e.flow); 61 if (!inq[e.to]) { Q.push(e.to); inq[e.to] = 1; } 62 } 63 } 64 } 65 if (d[t] == INF) return false; 66 flow += a[t]; 67 cost += (LL)d[t] * (LL)a[t]; 68 for (int u = t; u != s; u = edges[p[u]].from){ 69 edges[p[u]].flow += a[t]; 70 edges[p[u] ^ 1].flow -= a[t]; 71 72 } 73 return true; 74 } 75 76 void MincostMaxdflow(int s, int t, LL & cost) 77 { 78 int flow = 0; cost = 0; 79 while (BellmanFord(s, t, flow, cost) ); 80 //return flow; 81 } 82 }t; 83 84 int n,m; 85 86 int main() 87 { 88 //freopen("D:\input.txt", "r", stdin); 89 int T; 90 scanf("%d",&T); 91 int u,v,d; 92 while(T--) 93 { 94 scanf("%d%d",&n,&m); 95 int src=0,dst=2*n+1; 96 t.init(dst+1); 97 for(int i=1;i<=n;i++) 98 { 99 t.AddEdge(src,i,1,0); 100 t.AddEdge(i+n,dst,1,0); 101 } 102 for(int i=0;i<m;i++) 103 { 104 scanf("%d%d%d",&u,&v,&d); 105 t.AddEdge(u,v+n,1,d); 106 } 107 long long cost; 108 t.MincostMaxdflow(src,dst,cost); 109 printf("%d ",cost); 110 } 111 return 0; 112 }