[poj] 2396 [zoj] 1994 budget || 有源汇的上下界可行流
2018-01-07 11:53
549 查看
poj原题
zoj原题
//注意zoj最后一行不要多输出空行
现在要针对多赛区竞赛制定一个预算,该预算是一个行代表不同种类支出、列代表不同赛区支出的矩阵。组委会曾经开会讨论过各类支出的总和,以及各赛区所需支出的总和。另外,组委会还讨论了一些特殊的约束条件。组委会的任务是制定一个满足所有约束条件且行列和满足要求的预算。
有源汇的上下界可行流。
1、建原图(对于上界Max和下界Min的边连边为Max-Min,像无源汇一样记录extra)
2、在t和s(原图)见连接一条inf的边,使原图变为无源汇
3、建虚拟源汇S和T,按无源汇建图
4、跑最大流
5、判断是否可行(==sum)
#include<cstdio> #include<algorithm> #define N 250 #define M 100010 #define inf 0x3f3f3f3f #define fir first #define sec second using namespace std; struct hhh { int to,w,next,f,lower; }edge[M]; int cnt=1,head ,dis ,cur ; int TT,n,m,s,t,ans,sum,q ,r,extra ,A ; int Q,a,b,x; char c[3]; pair <int,int> g ; int read() { int ans=0,fu=1; char j=getchar(); for (;j<'0' || j>'9';j=getchar()) if (j=='-') fu=-1; for (;j>='0' && j<='9';j=getchar()) ans*=10,ans+=j-'0'; return ans*fu; } void init() { ans=sum=0; cnt=1; for (int i=1;i<=n+m+5;i++) head[i]=extra[i]=0; } int add(int u,int v,int w,int p) { edge[++cnt].to=v;edge[cnt].next=head[u];edge[cnt].w=w;edge[cnt].f=0;edge[cnt].lower=p;head[u]=cnt; edge[++cnt].to=u;edge[cnt].next=head[v];edge[cnt].w=0;edge[cnt].f=0;edge[cnt].lower=p;head[v]=cnt; return cnt-1; } bool ADD(int u,int v,char d,int w) { pair <int,int> &now=g[u][v]; if (d=='=') { if (now.fir<=w && w<=now.sec) now=make_pair(w,w); else return 0; } else if (d=='>') { w++; if (now.sec>=w) now.fir=max(now.fir,w); else return 0; } else { w--; if (now.fir<=w) now.sec=min(now.sec,w); else return 0; } return 1; } bool bfs(int S,int T) { for (int i=0;i<=T;i++) cur[i]=head[i],dis[i]=-1; dis[S]=1; q[r=1]=S; for (int l=1;l<=r;l++) { int u=q[l]; for (int i=head[u],v;i;i=edge[i].next) if (edge[i].w>edge[i].f && dis[v=edge[i].to]==-1) { dis[v]=dis[u]+1; q[++r]=v; if (v==T) return 1; } } return 0; } int dfs(int u,int flow,int T) { if (u==T || flow==0) return flow; int ret=0,delta; for (int &i=cur[u],v;i;i=edge[i].next) if (edge[i].w-edge[i].f && dis[v=edge[i].to]==dis[u]+1) { delta=dfs(v,min(edge[i].w-edge[i].f,flow-ret),T); if (delta) { edge[i].f+=delta; edge[i^1].f-=delta; ret+=delta; if (ret==flow) break; } } if (ret!=flow) dis[u]=-1; return ret; } int dinic(int S,int T) { int ans=0; while (bfs(S,T)) ans+=dfs(S,inf,T); return ans; } bool solve() { for (int i=1;i<=n;i++) for (int j=1,x,y;j<=m;j++) { x=g[i][j].fir;y=g[i][j].sec; A[i][j]=add(i,n+j,y-x,x); extra[i]-=x;extra[n+j]+=x; } add(t,s,inf,0); int ss=t+1,tt=t+2,sum=0; for (int i=s;i<=t;i++) { if (extra[i]>0) add(ss,i,extra[i],0),sum+=extra[i]; if (extra[i]<0) add(i,tt,-extra[i],0); } int flow=dinic(ss,tt); return flow==sum; } int main() { TT=read(); while (TT--) { n=read(); m=read(); s=0; t=n+m+1; init(); for (int i=1;i<=n;i++) x=read(),add(s,i,0,x),extra[s]-=x,extra[i]+=x; for (int i=1;i<=m;i++) x=read(),add(n+i,t,0,x),extra[n+i]-=x,extra[t]+=x; for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) g[i][j]=make_pair(0,inf); Q=read(); bool flag=1; while (Q--) { a=read(); b=read(); scanf("%s",c); x=read(); if (!a && !b) { for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) flag&=ADD(i,j,c[0],x); } else if (!a) for (int i=1;i<=n;i++) flag&=ADD(i,b,c[0],x); else if (!b) for (int i=1;i<=m;i++) flag&=ADD(a,i,c[0],x); else flag&=ADD(a,b,c[0],x); } if (!flag || !solve()) puts("IMPOSSIBLE"); else { for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) printf("%d%c",edge[A[i][j]].f+edge[A[i][j]].lower," \n"[j==m]); } } return 0; }
相关文章推荐
- poj 2396 zoj 1994 Budget(有源汇上下界的可行流)
- 【有源汇有上下界可行流】POJ-2396(ZOJ-1994) Budget
- POJ 2396 Budget 有源汇有上下界的可行流
- ZOJ 1994 Budget 有源汇上下界网络流 可行流
- poj 2396 Budget--有源汇+有上下界+可行流
- POJ 2396 - Budget 有源汇的上下界可行流
- poj2396 Budget(有源汇的有上下界的可行流)
- 【POJ 2396 Budget】 有上下界的可行流
- poj2396 Budget&&ZOJ1994 Budget[有源汇上下界可行流]
- poj 2396 Budget(有源汇上下界可行流)
- POJ 2396 有源汇的上下界可行流(好题)
- POJ 2396 有上下界有源汇可行流
- POJ 2396 Budget(无源汇网络有上下界的可行流-Dinic)
- POJ 2396 Budget (有源汇有上下界最大流)
- poj 2396(有源汇的上下界可行流。。。。。dinic)
- poj 2396 Budget (有源汇有上下界的网络流)
- poj 2396 Budget(有源汇上下界可行流)
- poj 2396(有源汇的上下界可行流。。。。。dinic)
- POJ 2396 有源有汇有上下界可行流问题
- POJ 2396 Budget 有上下界的可行流