hdu3157 有源汇上下界最小流

来源:互联网 发布:电力行业大数据应用 编辑:程序博客网 时间:2024/05/21 22:56
/*有源汇上下限最小流(1)添加超级源点ss和超级汇点tt (2)对于原有的边(u,v,l(u,v),c(u,v))(l为流量下限,c为流量上限),添加边(u,v,0,c-l); (3)对于每个结点i,记w[i]=l(u,i)-l(i,v)=f(i,v)-f(u,i);出-入   若w[i]>0,添加边(ss,i,w[i]),若w[i]<0,添加边(i,tt,-w[i]); (4)求解ss-tt的最大流,记为f1(5)添加(t,s,INF),求ss-tt的最大流,记为f2(6)如f1+f2==sum,则有最小流,则[t,s]的流量就是最小流,即edge[id^1].flow*/#include <iostream>#include<stdio.h> #include <algorithm>using namespace std;const int INF=0x3fff3ff;const int maxn=1500;struct EDGE{int to,flow,next;}edge[maxn];int head[maxn],cnt;int pre[maxn];int cur[maxn];int gap[maxn];int level[maxn];int w[maxn];int s,t,ss,tt,tot,sum;inline void addedge(int u,int v,int flow){edge[cnt].to=v;edge[cnt].flow=flow;edge[cnt].next=head[u];head[u]=cnt++;edge[cnt].to=u;edge[cnt].flow=0;edge[cnt].next=head[v];head[v]=cnt++;}void build_graph(int n,int m){s=n+1,t=s+1,ss=t+1,tt=ss+1,cnt=0,sum=0,tot=tt;memset(head,-1,sizeof(head));memset(w,0,sizeof(w));for(int i=1;i<=m;i++){char st1[10],st2[10];int l,u,v;scanf("%s%s%d",st1,st2,&l);if(st1[0]=='+')u=s;else sscanf(st1,"%d",&u);if(st2[0]=='-')v=t;else sscanf(st2,"%d",&v);w[u]-=l;w[v]+=l;addedge(u,v,INF);}for(int i=1;i<=tot;i++)if(w[i]>0)addedge(ss,i,w[i]);else if(w[i]<0)addedge(i,tt,-w[i]),sum+=-w[i];}int sap(int start,int end,int tot)//别打成s,t{memset(gap,0,sizeof(gap));memset(pre,-1,sizeof(pre));memset(level,0,sizeof(level));int u=start,ans=0,inf=INF;gap[0]=tot;for(int i=0;i<=tot;i++)cur[i]=head[i];while(level[start]<tot){bool flag=0;for(int &i=cur[u];i!=-1;i=edge[i].next){int v=edge[i].to;if(edge[i].flow&&level[u]==level[v]+1){flag=1;inf=min(inf,edge[i].flow);pre[v]=u;u=v;if(u==end){while(u!=start){u=pre[u];edge[cur[u]].flow-=inf;edge[cur[u]^1].flow+=inf;}ans+=inf;inf=INF;}break;}}if(!flag){if(--gap[level[u]]==0)break;int minn=tot;for(int i=head[u];i!=-1;i=edge[i].next)if(edge[i].flow&&level[edge[i].to]<minn){minn=level[edge[i].to];cur[u]=i;}level[u]=minn+1;gap[minn+1]++;if(u!=start)u=pre[u];}}return ans;}int main(){int n,m;while(scanf("%d %d",&n,&m),n+m){build_graph(n,m);int f1=sap(ss,tt,tot);int id=cnt;addedge(t,s,INF);       //重新添加边int f2=sap(ss,tt,tot);if(f1+f2!=sum)printf("impossible\n");  else printf("%d\n",edge[id^1].flow);  //注意id}return 0;}

0 0
原创粉丝点击