zoukankan      html  css  js  c++  java
  • 图论:费用流-SPFA+EK

    利用SPFA+EK算法解决费用流问题

    例题不够裸,但是还是很有说服力的,这里以Codevs1227的方格取数2为例子来介绍费用流问题

    这个题难点在建图上,我感觉以后还要把网络流建模想明白才能下手去做这种题,老实说挺难的

    先直接给出建图的代码:

    scanf("%d",&x);
                //把每个节点拆成两个,分别为ai和bi
                //ai向bi连边,费用为权值,容量为1 
                //再连边,费用为0,容量为k,保证联通
                addedge((i-1)*n+j,(i-1)*n+j+n*n,1,x);
                addedge((i-1)*n+j,(i-1)*n+j+n*n,k,0);
                //让bi能往下面或者左面走 
                if(j<n)
                    addedge((i-1)*n+j+n*n,(i-1)*n+j+1,k,0);
                if(i<n)
                    addedge((i-1)*n+j+n*n,i*n+j,k,0);

    然后给出完整实现,请记住cnt初始必须是1,为了和^配套使用

    否则RE???

    差点儿把以后的自己坑死

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 const int maxn=6005;
     6 const int maxm=1000005;
     7 const int INF=0x7fffffff;
     8 int n,k,cnt=1;
     9 bool inq[maxn];
    10 int g[maxn],dis[maxn],q[maxm],from[maxn];
    11 long long ans;
    12 struct Edge{int from,to,v,c,next;}e[maxm];
    13 void addedge(int u,int v,int w,int c)  //cost是费用 
    14 {
    15     e[++cnt].from=u;e[cnt].to=v;e[cnt].v=w;e[cnt].c=c;
    16     e[cnt].next=g[u];g[u]=cnt;
    17     
    18     e[++cnt].from=v;e[cnt].to=u;e[cnt].v=0;e[cnt].c=-c;
    19     e[cnt].next=g[v];g[v]=cnt;
    20 }
    21 bool spfa()
    22 {
    23     int t=0,w=1,u;
    24     memset(dis,-1,sizeof(dis));
    25     q[0]=0;dis[0]=0;inq[0]=1;
    26     while(t<w)
    27     {
    28         u=q[t];t++;
    29         for(int tmp=g[u];tmp;tmp=e[tmp].next)
    30         {
    31             if(e[tmp].v>0&&dis[u]+e[tmp].c>dis[e[tmp].to])
    32             {
    33                 dis[e[tmp].to]=dis[u]+e[tmp].c;
    34                 from[e[tmp].to]=tmp;
    35                 if(!inq[e[tmp].to])
    36                     {q[w]=e[tmp].to;w++;inq[e[tmp].to]=1;}
    37             }
    38         }
    39         inq[u]=0;
    40     }
    41     if(dis[6000]==-1) return 0;
    42     return 1;
    43 }
    44 void mincf()
    45 {
    46     int sum=INF;
    47     int tmp=from[6000];
    48     while(tmp)
    49     {
    50         sum=min(sum,e[tmp].v);
    51         tmp=from[e[tmp].from];
    52     }
    53     tmp=from[6000];
    54     while(tmp)
    55     {
    56         e[tmp].v-=sum;
    57         e[tmp^1].v+=sum;
    58         ans+=sum*e[tmp].c;
    59         tmp=from[e[tmp].from];
    60     }
    61 }
    62 int main()
    63 {
    64     int x;
    65     scanf("%d%d",&n,&k);
    66     for(int i=1;i<=n;i++)
    67         for(int j=1;j<=n;j++)
    68         {
    69             scanf("%d",&x);
    70             //把每个节点拆成两个,分别为ai和bi
    71             //ai向bi连边,费用为权值,容量为1 
    72             //再连边,费用为0,容量为k,保证联通
    73             addedge((i-1)*n+j,(i-1)*n+j+n*n,1,x);
    74             addedge((i-1)*n+j,(i-1)*n+j+n*n,k,0);
    75             //让bi能往下面或者左面走 
    76             if(j<n)
    77                 addedge((i-1)*n+j+n*n,(i-1)*n+j+1,k,0);
    78             if(i<n)
    79                 addedge((i-1)*n+j+n*n,i*n+j,k,0);    
    80         }
    81     //源点和汇点 
    82     addedge(0,1,k,0);
    83     addedge(n*n*2,6000,k,0); 
    84     while(spfa()) mincf();
    85     printf("%lld",ans);
    86     return 0;
    87 }

    还有一点就是这个题是最大费用最大流,最小费用最大流还有ZKW费用流以后再介绍

  • 相关阅读:
    Android Studio 自定义签名,代码段快捷键
    Hardware Acceleration
    AsyncTask
    Process and Threads
    android通讯录开发及优化
    短信验证码SDK
    怎样让Mac成为一个有效的生产力工具
    GitHub开源项目
    jquery $(document).ready() 与window.onload的区别
    【Ionic+AngularJS 开发】之『个人日常管理』App(二)
  • 原文地址:https://www.cnblogs.com/aininot260/p/9450474.html
Copyright © 2011-2022 走看看