好题,回路的问题一般都要转化为度数来做
若原图的基图不连通,或者存在某个点的入度或出度为0则无解。
统计所有点的入度出度之差di
对于di>0的点,加边(s,i,di,0);
对于di<0的点,加边(i,t,-di,0);
对原图中的每条边(i,j),在网络中加边(i,j,inf,边权),
最小费用流的解加上原图所有边权和即为答案。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 
  6 using namespace std;
  7 struct way{int po,next,flow,cost;} e[40010];
  8 const int inf=100000007;
  9 int pre[110],p[110],cur[110],d[110],fa[110],cd[110],rd[110],q[2000010];
 10 bool v[110];
 11 int n,m,len,t;
 12 
 13 int getf(int x)
 14 {
 15     if (fa[x]!=x) fa[x]=getf(fa[x]);
 16     return fa[x];
 17 }
 18 
 19 bool check()
 20 {
 21     for (int i=1; i<=n; i++)
 22         if (!rd[i]||!cd[i]||getf(i)!=getf(1)) return 0;
 23     return 1;
 24 }
 25 
 26 void add(int x,int y,int f,int c)
 27 {
 28      e[++len].po=y;
 29      e[len].flow=f;
 30      e[len].cost=c;
 31      e[len].next=p[x];
 32      p[x]=len;
 33 }
 34 
 35 void build(int x,int y, int f, int c)
 36 {
 37      add(x,y,f,c);
 38      add(y,x,0,-c);
 39 }
 40 
 41 bool spfa()
 42 {
 43      int f=1,r=1;
 44      for (int i=1; i<=t; i++) d[i]=inf;
 45      memset(v,false,sizeof(v));
 46      d[0]=0; q[1]=0;
 47      while (f<=r)
 48      {
 49            int x=q[f++];
 50            v[x]=0;
 51            for (int i=p[x]; i!=-1; i=e[i].next)
 52            {
 53                int y=e[i].po;
 54                if (e[i].flow&&d[x]+e[i].cost<d[y])
 55                {
 56                   d[y]=d[x]+e[i].cost;
 57                   pre[y]=x; cur[y]=i;
 58                   if (!v[y])
 59                   {
 60                      q[++r]=y;
 61                      v[y]=1;
 62                   }
 63                }
 64            }
 65      }
 66      return d[n]<inf;
 67 }
 68 
 69 int mincost()
 70 {
 71     int j,s=0;
 72     while (spfa())
 73     {
 74           int neck=inf;
 75           for (int i=t; i; i=pre[i])
 76           {
 77               j=cur[i];
 78               neck=min(neck,e[j].flow);
 79           }
 80           s+=d[t]*neck;
 81           for (int i=t; i; i=pre[i])
 82           {
 83               j=cur[i];
 84               e[j].flow-=neck;
 85               e[j^1].flow+=neck;
 86           }
 87     }
 88     return s;
 89 }
 90 
 91 int main()
 92 {
 93     int cas;
 94     scanf("%d",&cas);
 95     while (cas--)
 96     {
 97         scanf("%d%d",&n,&m);
 98         memset(p,255,sizeof(p)); len=-1;
 99         memset(rd,0,sizeof(rd));
100         memset(cd,0,sizeof(cd));
101         for (int i=1; i<=n; i++) fa[i]=i;
102         int ans=0;
103         for (int i=1; i<=m; i++)
104         {
105             int x,y,u,v,z;
106             scanf("%d%d%d",&x,&y,&z);
107             cd[++x]++;rd[++y]++;
108             build(x,y,inf,z);
109             u=getf(x),v=getf(y);
110             if (u!=v) fa[u]=v;
111             ans+=z;
112         }
113         if (!check())
114         {
115             puts("-1");
116             continue;
117         }
118         t=n+1;
119         for (int i=1; i<=n; i++)
120             if (rd[i]>cd[i]) build(0,i,rd[i]-cd[i],0);
121             else build(i,t,cd[i]-rd[i],0);
122         ans+=mincost();
123         printf("%d\n",ans);
124     }
125 }
View Code

 

posted on 2017-01-23 22:15  acphile  阅读(222)  评论(0编辑  收藏  举报