zoukankan      html  css  js  c++  java
  • 【sgu194】 无源无汇有容量上下界的可行流

    题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=20757

    题目大意:给出一个屋源无汇的网络,每条边都有容量上下界,让你求一个可行方案使得每个节点都流量守恒。

    解题思路:题目既然无源无汇点,那么所有节点都应该满足”入流=出流“这个流量平衡条件,为了方便解题,我们令每条边的容量下界为0,此刻容量上界变成了up-down(上界减去下届),我们定义一个du[]数组保存每个节点的入流之和与出流之和的差,建一个超级源点和一个超级汇点,当du[i]>0,说明入流大于出流,为了满足流量守恒,连一条st到i容量为du[i]的边,当du[i]<0,说明出流大于入流,连一条i到sd容量为-du[i]的边。 

        最构造的网络进行一次最大流,当且仅当所有附加弧满载时原网络有可行流,否则没有。

    View Code
      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cmath>
      4 #include <algorithm>
      5 #include <cstring>
      6 using namespace std;
      7 
      8 const int mn=22222;
      9 const int mm=1000000;
     10 const int oo=0x3fffffff;
     11 int node, st, sd, edge, Edge;
     12 int reach[mm], flow[mm], next[mm];
     13 int head[mn], work[mn], dis[mn], que[mn];
     14 int du[mm], ans[mm], id[mm], dn[mm];
     15 
     16 inline void init(int _node, int _st, int _sd)
     17 {
     18     node=_node, st=_st, sd=_sd;
     19     for(int i=0; i<node; i++)
     20         head[i]=-1;
     21     edge=0;
     22 }
     23 
     24 inline void addedge(int u, int v, int c1, int c2, int ID)
     25 {
     26     id[edge]=ID, reach[edge]=v, flow[edge]=c1, next[edge]=head[u],head[u]=edge++;
     27     id[edge]=0, reach[edge]=u, flow[edge]=c2, next[edge]=head[v],head[v]=edge++;
     28 }
     29 
     30 bool bfs()
     31 {
     32     int u, v, l=0, h=0;
     33     for(int i=0; i<node; i++) dis[i]=-1;
     34     que[l++]=st;
     35     dis[st]=0;
     36     while(l!=h)
     37     {
     38         u=que[h++];
     39         if(h==mn) h=0;
     40         for(int i=head[u]; i>=0; i=next[i])
     41         {
     42             v=reach[i];
     43             if(flow[i]&&dis[v]<0)
     44             {
     45                 dis[v]=dis[u]+1;
     46                 que[l++]=v;
     47                 if(l==mn) l=0;
     48                 if(v==sd) return true;
     49             }
     50         }
     51     }
     52     return false;
     53 }
     54 
     55 int dfs(int u, int exp)
     56 {
     57     if(u==sd) return exp;
     58     for(int &i=work[u]; i>=0; i=next[i])
     59     {
     60         int v=reach[i], tp;
     61         if(flow[i]&&dis[v]==dis[u]+1&&(tp=dfs(v,min(flow[i],exp))>0))
     62         {
     63             flow[i]-=tp;
     64             flow[i^1]+=tp;
     65             return tp;
     66         }
     67     }
     68     return 0;
     69 }
     70 
     71 void Dinic()
     72 {
     73     while(bfs())
     74     {
     75         for(int i=0; i<node; i++) work[i]=head[i];
     76         while(dfs(st,oo));
     77     }
     78 }
     79 
     80 int main()
     81 {
     82     int n,m;
     83     while(~scanf("%d%d",&n,&m))
     84     {
     85         init(n+2,0,n+1);
     86         for(int i=1; i<=m; i++)
     87         {
     88             int u, v, down, up;
     89             scanf("%d%d%d%d",&u,&v,&down,&up);
     90             addedge(u,v,up-down,0,i);
     91             du[u]-=down;
     92             du[v]+=down;
     93             dn[i]=down;
     94         }
     95         Edge=edge;
     96         for(int i=1; i<=n; i++)
     97         {
     98             if(du[i]>0) addedge(st,i,du[i],0,0);
     99             if(du[i]<0) addedge(i,sd,-du[i],0,0);
    100         }
    101         Dinic();
    102         bool flag=true;
    103         for(int i=head[st]; i>=0; i=next[i])
    104             if(flow[i]>0)
    105             {
    106                 flag=false;
    107                 break;
    108             }
    109         if(!flag) puts("NO");
    110         else
    111         {
    112             puts("YES");
    113             for(int i=0; i<Edge; i++) ans[id[i]]=flow[i^1];
    114             for(int i=1; i<=m; i++)
    115                 printf("%d\n",ans[i]+dn[i]);
    116         }
    117     }
    118     return 0;
    119 }
  • 相关阅读:
    MCMC等采样算法
    【模拟退火】旅行商问题
    团队项目博客汇总
    2018年春季学期-助教总结
    linux简单命令常用随记
    记一次计算机网络作业
    [东北师大软工]Week2-作业2:个人项目实战 初步测试结果
    为什么你学过Java却忘光了——记第一次助教同学见面会
    ahk打印成pdf记录
    PSP总结报告
  • 原文地址:https://www.cnblogs.com/kane0526/p/2990184.html
Copyright © 2011-2022 走看看