http://poj.org/problem?id=2396 (題目連接)ios
給出一個矩陣,給出每一行每一列的和,以及若干限制條件,限制了其中每個元素的上下界,求一種可行的方案使得每一行每一列數的和知足要求。網絡
我已經徹底沒有網絡流思惟了,江化了= 。=spa
源點向每一行和每一列連上下界都爲其對應和的邊,行與列之間連邊,邊的上下界爲對應格子的取值範圍。而後跑上下界網絡流找一條可行流就能夠了。blog
mdzz初值設太大爆int了= =,還有這種事。。get
// poj2396 #include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<cmath> #include<queue> #define LL long long #define inf (1ll<<29) #define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout) using namespace std; const int maxn=1010; int head[maxn],fi[maxn],d[maxn],upp[maxn][maxn],low[maxn][maxn],id[maxn][maxn]; int n,m,s,c,t,S,T,SS,TT,cnt,sum,flag; struct edge {int to,next,w;}e[maxn*maxn]; void link(int u,int v,int w) { e[++cnt]=(edge){v,head[u],w};head[u]=cnt; e[++cnt]=(edge){u,head[v],0};head[v]=cnt; } bool bfs() { memset(d,-1,sizeof(d)); queue<int> q;q.push(s);d[s]=0; while (!q.empty()) { int x=q.front();q.pop(); for (int i=head[x];i;i=e[i].next) if (e[i].w && d[e[i].to]<0) d[e[i].to]=d[x]+1,q.push(e[i].to); } return d[t]>0; } int dfs(int x,int f) { if (x==t || f==0) return f; int w,used=0; for (int i=head[x];i;i=e[i].next) if (e[i].w && d[e[i].to]==d[x]+1) { w=dfs(e[i].to,min(e[i].w,f-used)); used+=w,e[i].w-=w,e[i^1].w+=w; if (used==f) return used; } if (!used) d[x]=-1; return used; } int Dinic(int x,int y) { int flow=0;s=x,t=y; while (bfs()) flow+=dfs(x,inf); return flow; } void modify(int x,int y,char *r,int val) { if (r[0]=='<') upp[x][y]=min(upp[x][y],val-1); if (r[0]=='>') low[x][y]=max(low[x][y],val+1); if (r[0]=='=') { if (val>=low[x][y] && val<=upp[x][y]) upp[x][y]=low[x][y]=val; else flag=0; } } int main() { int Case;scanf("%d",&Case); while (Case--) { scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) upp[i][j]=1000,low[i][j]=0; memset(head,0,sizeof(head)); memset(fi,0,sizeof(fi)); S=0,T=n+m+1;SS=T+1,TT=SS+1; cnt=1;sum=0;flag=1; for (int x,i=1;i<=n;i++) { scanf("%d",&x); fi[S]-=x,fi[i]+=x; } for (int x,i=1;i<=m;i++) { scanf("%d",&x); fi[T]+=x,fi[i+n]-=x; } scanf("%d",&c);char ch[10]; for (int x,y,z,i=1;i<=c;i++) { scanf("%d%d%s%d",&x,&y,ch,&z); if (!x && !y) for (int j=1;j<=n;j++) for (int k=1;k<=m;k++) modify(j,k,ch,z); else if (!x) for (int j=1;j<=n;j++) modify(j,y,ch,z); else if (!y) for (int j=1;j<=m;j++) modify(x,j,ch,z); else modify(x,y,ch,z); } for (int i=1;i<=n && flag;i++) for (int j=1;j<=m && flag;j++) { if (low[i][j]<=upp[i][j]) { fi[i]-=low[i][j],fi[n+j]+=low[i][j]; link(i,n+j,upp[i][j]-low[i][j]); id[i][j]=cnt-1; } else flag=0; } if (!flag) {puts("IMPOSSIBLE\n");continue;} for (int i=S;i<=T;i++) { if (fi[i]<0) link(i,TT,-fi[i]); else link(SS,i,fi[i]),sum+=fi[i]; } link(T,S,inf); if (sum!=Dinic(SS,TT)) {puts("IMPOSSIBLE\n");continue;} for (int i=1;i<=n;i++) { for (int j=1;j<=m;j++) printf("%d ",low[i][j]+e[id[i][j]^1].w); puts(""); } puts(""); } return 0; }