题意:给出一张有n个点m条边带权的有向图,要你找出若干个回路并且使得所有的点都在某个回路上,且所有的点只能出现在一个回路中,求由n条边组成的若干回路的最小权值。
所有点只能出现在一个回路中,因此,所有的点都对应唯一的前驱或后继,因此这就是一个匹配问题。如果有边(u->v),边权为w,那它就对应二分图中的一条边(u,v',w),直接这样建图跑KM就可以了。当然,用这种写法的费用流会比较慢。

1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 #include <queue> 5 #define maxn 410 6 #define maxm 70000 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 bool flag; 14 void init(){ 15 e = 0; 16 memset(first,-1,sizeof(first)); 17 } 18 19 void add_edge(int a,int b,int cc,int ww){ 20 cap[e] = cc;cost[e] = ww;v[e] = b; 21 next[e] = first[a];first[a] = e++; 22 cap[e] = 0;cost[e] = -ww;v[e] = a; 23 next[e] = first[b];first[b] = e++; 24 } 25 26 int d[maxn],pre[maxn],pos[maxn]; 27 bool vis[maxn]; 28 29 bool spfa(int s,int t){ 30 memset(pre,-1,sizeof(pre)); 31 memset(vis,0,sizeof(vis)); 32 queue<int> Q; 33 for(int i = 0;i <= n;i++) d[i] = INF; 34 Q.push(s);pre[s] = s;d[s] = 0;vis[s] = 1; 35 while(!Q.empty()){ 36 int u = Q.front();Q.pop(); 37 vis[u] = 0; 38 for(int i = first[u];i != -1;i = next[i]){ 39 if(cap[i] > 0 && d[u] + cost[i] < d[v[i]]){ 40 d[v[i]] = d[u] + cost[i]; 41 pre[v[i]] = u;pos[v[i]] = i; 42 if(!vis[v[i]]) vis[v[i]] = 1,Q.push(v[i]); 43 } 44 } 45 } 46 return pre[t] != -1; 47 } 48 49 int Mincost; 50 int Maxflow; 51 52 int MinCostFlow(int s,int t,int nn){ 53 Mincost = 0,Maxflow = 0,n = nn; 54 while(spfa(s,t)){ 55 int min_f = INF; 56 for(int i = t;i != s;i = pre[i]) 57 if(cap[pos[i]] < min_f) min_f = cap[pos[i]]; 58 Mincost += d[t] * min_f; 59 Maxflow += min_f; 60 for(int i = t;i != s;i = pre[i]){ 61 cap[pos[i]] -= min_f; 62 cap[pos[i]^1] += min_f; 63 } 64 } 65 return Mincost; 66 } 67 }; 68 MCMF g; 69 int main() 70 { 71 int n,m,t; 72 scanf("%d",&t); 73 while(t--){ 74 scanf("%d%d",&n,&m); 75 g.init(); 76 int S = 0,T = 2*n+1; 77 for(int i = 1;i <= n;i++) 78 g.add_edge(S,i,1,0),g.add_edge(i+n,T,1,0); 79 for(int i = 0;i < m;i++){ 80 int a,b,c; 81 scanf("%d%d%d",&a,&b,&c); 82 g.add_edge(a,b+n,1,c); 83 } 84 printf("%d ",g.MinCostFlow(S,T,T)); 85 } 86 return 0; 87 }