HDU 3157 有源汇上下界最小流

来源:互联网 发布:nba95年总决赛数据 编辑:程序博客网 时间:2024/05/21 17:38

可以直接无视那长长的段落。。

+ 表示是源点, - 表示是汇点

1,2,3,,,...n 表示n个节点

要求是否存在满足 下界限制的最小的流

如果不存在输出 impossible


最下界最小流。。 看 周源  《一种简易的方法求解流量有上下界的网络中网络流问题》  里面介绍的时候是讲用二分思想。。但是 = =有更简单的

先求是否存在可行流。。

则判断 无源无汇情况下是否存在可行流,  则用无源无汇的建图方式

....

src0,dest0  为 图中给出的 源点与汇点,  s,t为新增的附加源点与汇点

1. 构造附加网络(不添加[t,s]边) 
2. 对s、t求最大流    

---- 上面为无源无汇建图方式 ,  src0,dest0 是 + 与 - 那两个题目中所给的源点跟汇点,所以要放到无源无汇中跑

求出此时的 最大流 sum1

之后
3. 添加[ dest0 ,src0 ]  无穷大 这条边 
4. 对s、t  再次求最大流 

此时得到最大流  sum2


5. 若s、t  的 sum1 + sum2 == 无源无汇时的满流,则[t,s]的流量就是最小流 

从残留网络中输出答案即可


//tpl  //ipqhjjybj_tpl.h  //header.h  /*src0,dest0  为 图中给出的 源点与汇点,  s,t为新增的附加源点与汇点1. 构造附加网络(不添加[t,s]边) 2. 对s、t求最大流    ---- 上面为无源无汇建图方式 ,  src0,dest0 是 + 与 - 那两个题目中所给的源点跟汇点,所以要放到无源无汇中跑求出此时的 最大流 sum1之后3. 添加[ dest0 ,src0 ]  无穷大 这条边 4. 对s、t  再次求最大流 此时得到最大流  sum25. 若s、t  的 sum1 + sum2 == 无源无汇时的满流,则[t,s]的流量就是最小流 从残留网络中输出答案即可 */#include <cstdio>  #include <cstdlib>  #include <map>  #include <set>  #include <algorithm>  #include <cstring>  #include <iostream>  #include <vector>  #include <string>  #include <queue>  #include <sstream>  #include <math.h>    #define mp(x,y) make_pair(x,y)  #define pii pair<int,int>  #define pLL pair<long long ,long long>  #define pb(x) push_back(x)  #define rep(i,j,k) for(int i = j; i < k;i++)    #define MAX(x,a)  x=((x)<(a))?(a):(x);  #define MIN(x,a)  x=((x)>(a))?(a):(x);    using namespace std;    const int N = 500;  int n,m,tot;  int s,t;  int sum;  struct node{      int u,v,w,next;      node(){}      node(int _u,int _v,int _w,int _next){          u=_u,v=_v,w=_w,next=_next;      }  }edge[N*N];  int head[N],cur[N],dis[N];  int pre[N],gap[N],aug[N];  const int oo=0x3f3f3f3f;  void addEdge(int u,int v,int w){      edge[tot]=node(u,v,w,head[u]);      head[u]=tot++;      edge[tot]=node(v,u,0,head[v]);      head[v]=tot++;  }    int SAP(int s,int e,int n){      int max_flow=0,v,u=s;      int id,mindis;      aug[s]=oo;      pre[s]=-1;      memset(dis,0,sizeof(dis));      memset(gap,0,sizeof(gap));      gap[0]=n;        for(int i=0;i <= n;i++)          cur[i]=head[i];        while(dis[s]<n){          if(u==e){              max_flow += aug[e];              for(v=pre[e]; v!=-1; v=pre[v]){                  int ed=cur[v];                  edge[ed].w -= aug[e];                  edge[ed^1].w += aug[e];                  aug[v]-=aug[e];                  if(edge[ed].w==0) u=v;              }          }          bool flag=false;          for(id=cur[u]; id!=-1;id=edge[id].next){              v=edge[id].v;              if(edge[id].w > 0 && dis[u]==dis[v]+1){                  flag=true;                  pre[v]=u;                  cur[u]=id;                  aug[v]=min(aug[u],edge[id].w);                  u=v;                  break;              }          }          if(flag==false){              if(--gap[dis[u]] == 0) break;               int mindis=n;              for(id=head[u]; id!=-1; id=edge[id].next){                  v=edge[id].v;                  if(edge[id].w>0 && dis[v] < mindis){                      mindis = dis[v];                      cur[u]=id;                  }              }              dis[u] = mindis + 1;              gap[dis[u]]++;              if(u!=s)u=pre[u];          }      }      return max_flow;  }  char s1[10],s2[10];int in[N];int max_flow;int getNum(char fs[]){if(fs[0] == '+')return s;else if(fs[0] == '-') return t;else return atoi(fs);}int solve(){int i,src0,dest0;src0 = s, dest0 = t;s = n+2, t = n+3;rep(i,0,dest0+1)if(in[i]>0) addEdge(s,i,in[i]);else if(in[i]<0) addEdge(i,t,-in[i]),max_flow += -in[i];int ans1 = SAP(s,t,n+4);addEdge(dest0,src0,oo);int kk = SAP(s,t,n+4);if(kk+ans1 == max_flow)return edge[tot-1].w;else return -1;}int main(){while(scanf("%d %d",&n,&m)!=EOF){if(n==0 && m==0) break;memset(head,-1,sizeof(head));memset(in,0,sizeof(in));s = sum = tot =0; t=n+1;max_flow = 0;rep(i,0,m){int l,r,w;scanf("%s %s %d",s1,s2,&w);l = getNum(s1),r = getNum(s2); // printf("l=%d r=%d w=%d\n",l,r,w);addEdge(l,r,oo);in[r]+=w, in[l]-=w;}int ans=0;if((ans=solve())>=0) printf("%d\n",ans);else puts("impossible");}return 0;}


0 0
原创粉丝点击