1. 程式人生 > >poj 2396 Budget【有上下界的網絡流】

poj 2396 Budget【有上下界的網絡流】

scan turn sca bool mem cas spa bfs blog

第一步:建立無源匯有上下界的網絡模型 每行 i 作為一個點並連邊(s, i, Ri, Ri),每列 j 作為一個點並連邊(j, t, Cj, Cj),設 Uij, Lij 分別表示第 i 行第 j 列元素的上下界,初始時設 Uij=∞, Lij=0。按照給定的約束條 件不斷調整 Uij, Lij,若出現 Lij > Uij 的情況則已經不存在合法解。對所有元素加 邊(i, j, Lij, Uij)。另添加邊(t, s, 0, ∞)消去原網絡的源匯。

第二步:轉化為最大流模型 新建源 s’和匯 t’,對每條下界大於 0 的邊(i, j, Lij, Uij),加邊(i, t’, 0, Lij), (s’, j, 0, Lij)。 若新網絡中最大流等於所有下界之和,則原網絡存在可行流,即存在滿足所有約 束條件的矩陣。
————BY Edelweiss 《 網絡流建模匯總》

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
const int N=2000005,inf=1e9;
int n,m,q,h[N],cnt=1,le[N],s,t,S,T,sum,lm[2][205][205],fr[505][55];
bool flg;
char c[10];
struct qwe
{
    int ne,no,to,va;
}e[N];
int read()
{
    int
r=0,f=1; char p=getchar(); while(p>‘9‘||p<‘0‘) { if(p==‘-‘) f=-1; p=getchar(); } while(p>=‘0‘&&p<=‘9‘) { r=r*10+p-48; p=getchar(); } return r*f; } void add(int u,int v,int w) { cnt++; e[cnt].ne=h[u]; e[cnt].no=u; e[cnt].to=v; e[cnt].va=w; h[u]=cnt; } void
ins(int u,int v,int w) { if(!w) return; if(u==S) sum+=w; add(u,v,w); add(v,u,0); } void jiabian(int u,int v,int l,int r) { if(r<l) { flg=0; return; } ins(S,v,l); ins(u,T,l); ins(u,v,r-l); } bool bfs() { queue<int>q; memset(le,0,sizeof(le)); le[S]=1; q.push(S); while(!q.empty()) { int u=q.front(); q.pop(); for(int i=h[u];i;i=e[i].ne) if(e[i].va>0&&!le[e[i].to]) { le[e[i].to]=le[u]+1; q.push(e[i].to); } } return le[T]; } int dfs(int u,int f) { if(!f||u==T) return f; int us=0; for(int i=h[u];i&&us<f;i=e[i].ne) if(e[i].va>0&&le[e[i].to]==le[u]+1) { int t=dfs(e[i].to,min(e[i].va,f-us)); e[i].va-=t; e[i^1].va+=t; us+=t; } if(!us) le[u]=0; return us; } int dinic() { int re=0; while(bfs()) re+=dfs(S,inf); memset(fr,0,sizeof(fr));//cout<<re<<" "<<sum<<endl; if(re==sum) {//cout<<"ok"<<endl; for(int i=1;i<=cnt;i+=2) if(e[i].no>n&&e[i].no<=n+m&&e[i].to<=n+m) fr[e[i].to][e[i].no-n]=e[i].va; for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) printf("%d ",fr[i][j]+lm[0][i][j]); puts(""); } puts(""); } else puts("IMPOSSIBLE\n"); } int main() { int cas=read(); while(cas--) { n=read(),m=read(); memset(h,0,sizeof(h)); cnt=1,flg=1,sum=0; s=n+m+1,t=s+1,S=t+1,T=S+1; for(int i=1;i<=n;i++) { int x=read(); jiabian(s,i,x,x); } for(int i=1;i<=m;i++) { int x=read(); jiabian(i+n,t,x,x); } q=read(); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { lm[0][i][j]=0; lm[1][i][j]=inf; } while(q--) { int x=read(),y=read(); scanf("%s",c); int z=read(),k1,k2,k3,k4; if(x==0) k1=1,k2=n; else k1=k2=x; if(y==0) k3=1,k4=m; else k3=k4=y; for(int i=k1;i<=k2;i++) for(int j=k3;j<=k4;j++) { if(c[0]==‘>‘) lm[0][i][j]=max(lm[0][i][j],z+1); if(c[0]==‘=‘) lm[0][i][j]=max(lm[0][i][j],z); if(c[0]==‘<‘) lm[1][i][j]=min(lm[1][i][j],z-1); if(c[0]==‘=‘) lm[1][i][j]=min(lm[1][i][j],z); } } for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { jiabian(i,j+n,lm[0][i][j],lm[1][i][j]); if(flg==0) break; } jiabian(t,s,0,inf); if(!flg) puts("IMPOSSIBLE\n"); else dinic(); } return 0; }

poj 2396 Budget【有上下界的網絡流】