hdu3488 / hdu3435 / hdu1853 最小费用最大流 圈 拆点

  题目大意:

    在一个有向图中,求经过所有点的最小圈。

  思路:

    (如果是用二分图的完美匹配来做,那么直接上模版就好了)。http://www.cnblogs.com/Potato-lover/p/3991640.html

    用最小费用最大流的思路如下:

    首先是每个点都只能走一次,限制的点容量是用拆点来完成的。把i点拆为i和i+n两个点,建边i->i+n,这样i这个点负责入边,i+n点负责出边。这样不管有多少边与i相连,只能走一次i点。

    每个点都必须走。源点S(2*n+1)连向i, 容量为1,边权为0。i+n连向汇点E(2*n+2),容量为1,边权为0。对于输入的边a,b,w,建立a->b+n的边,容量为1,边权为w。

    然后就是用模版。这样下来,会发现,完美匹配的做法与最小流最大流的做法其实是一样的。完美匹配就是每个点必须且仅走一次,在这里可以理解为满流。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 using namespace std;
  6 
  7 const int N =1010, M=50010,INF=0x3f3f3f3f;
  8 struct node
  9 {
 10     int to, next, c ,f;//c是容量,f是费用
 11 }edge[M];
 12 int head[N],dis[N],load[N],p[N];
 13 bool vis[N];
 14 int tot,flow,cost;
 15 bool spfa(int S, int E,int n)
 16 {
 17     int que[N*10],qout,qin;
 18     memset(vis,0,sizeof(vis));
 19     memset(load,-1,sizeof(load));
 20     memset(p,-1,sizeof(p));
 21     for(int i=0;i<=n;i++)
 22         dis[i]=INF;
 23     qin=qout=0;
 24     que[qin++]=S;
 25     dis[S]=0;
 26     vis[S]=1;
 27     while(qin!=qout)
 28     {
 29         int u=que[qout++];
 30         vis[u]=0;
 31         for(int i=head[u];i!=-1;i=edge[i].next)
 32         {
 33             if(edge[i].c)
 34             {
 35                 int v=edge[i].to;
 36                 if(dis[v]-dis[u]>edge[i].f)
 37                 {
 38                     dis[v]=dis[u]+edge[i].f;
 39                     p[v]=u;
 40                     load[v]=i;
 41                     if(!vis[v])
 42                     {
 43                         vis[v]=1;
 44                         que[qin++]=v;
 45                     }
 46                 }
 47             }
 48         }
 49     }
 50     if(dis[E]==INF) return 0;
 51     return 1;
 52 }
 53 void MCF(int S, int E,int n)
 54 {
 55     int u,mn;
 56     flow=cost=0;
 57     while(spfa(S,E,n))
 58     {
 59         u=E; mn=INF;
 60         while(p[u]!=-1)
 61         {
 62             mn=min(edge[load[u]].c, mn);
 63             u=p[u];
 64         }
 65         u=E;
 66         while(p[u]!=-1)
 67         {
 68             edge[load[u]].c-=mn;
 69             edge[load[u]^1].c+=mn;
 70             u=p[u];
 71         }
 72         cost+=dis[E]*mn;
 73         flow+=mn;
 74     }
 75 }
 76 void addedge(int a,int b,int c,int d)
 77 {
 78     edge[tot].to=b;edge[tot].c=c;edge[tot].f=d;
 79     edge[tot].next=head[a];head[a]=tot++;
 80     edge[tot].to=a;edge[tot].c=0;edge[tot].f=-d;
 81     edge[tot].next=head[b];head[b]=tot++;
 82 }
 83 void init()
 84 {
 85     tot=0;
 86     memset(head,-1,sizeof(head));
 87 }
 88 int main()
 89 {
 90     //freopen("test.txt","r",stdin);
 91     int n,m,k,i,j,w,cas,s,e;
 92     scanf("%d",&cas);
 93     while(cas--)
 94     {
 95         init();
 96         scanf("%d%d",&n,&m);
 97         s=2*n+1;e=s+1;
 98         while(m--)
 99         {
100             scanf("%d%d%d",&i,&j,&w);
101             addedge(i,j+n,1,w);
102         }
103         for(i=1;i<=n;i++){
104             addedge(s,i,1,0);
105             addedge(i+n,e,1,0);
106         }
107         MCF(s,e,e);
108         printf("%d
",cost);
109     }
110     return 0;
111 }
View Code

 

原文地址:https://www.cnblogs.com/Potato-lover/p/3980109.html