zoukankan      html  css  js  c++  java
  • 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

     

  • 相关阅读:
    .Net Core小技巧
    调用Kubernetes API操作Kubernetes
    在CentOS 7+ 安装Kubernetes入门(单Master)
    Linux命令行基础
    使用wireshark学习TCP
    Redis原子性写入HASH结构数据并设置过期时间
    Vue使用小结
    JAVA & .NET创建对象构造函数调用顺序
    .NET 中的序列化 & 反序列化
    ASP.NET Core中使用Graylog记录日志
  • 原文地址:https://www.cnblogs.com/Potato-lover/p/3980109.html
Copyright © 2011-2022 走看看