题意: 给出一个 n*m的矩阵,知道了每一行元素的和(n个),每一列元素的和(m个)
给出t个条件:
a b c d
表示 a b 和 数字 d 满足条件 c
分析: 此题的最大流有下界的限制,用上下界最大流求解时,需要先去掉下界,判断是否存在可行流
将 1 到 n 行每行看作一个节点(1..n),将 1 到 m 列每列看作一个节点(n+1..n+m)
建立源点 s=0,汇点 t=n+m+1
在源点 s 和每一个行节点之间连一条上界是行数字的和下界为 0的边
在每一个列节点和和汇点t之间连一条上界是列数字的和下界为 0的边
如果 i 行 j 列的数字大于 x,就在 i 行节点和 j 列节点之间连一条上界为INF,下界为 x+1 的边
如果 i 行 j 列的数字小于 x,就在 i 行节点和 j 列节点之间连一条上界为x-1, 下界为 0 的边
如果等于,上下界都是x
建图之后, i 行与 j 列的流量就是 i,j的值
如果最大流等于所有行元素的和,就存在解,输出流量即可。
#include#include #define clr(x)memset(x,0,sizeof(x))#define maxn 300#define INF 0x1f1f1f1f#define min(a,b)(a)<(b)?(a):(b)int cap[maxn][maxn];int clow[maxn][maxn];int flow[maxn][maxn];void max_flow(int s,int t,int n){ int p[maxn],a[maxn],q[maxn]; int u,v,front,rear; for(;;) { clr(a); a[s]=INF; front=rear=0; q[rear++]=s; while(front '&&clow[i][j+n] w-1) cap[i][j+n]=w-1; } } if(sum1==sum2&&flag) { clr(flow); int rflow=limit_flow(s,t,t+1); if(rflow!=-1&&rflow==sum1) { for(i=1;i<=n;i++) for(j=1;j<=m;j++) printf("%d%c",flow[i][j+n],j==m?'\n':' '); } else printf("IMPOSSIBLE\n"); } else printf("IMPOSSIBLE\n"); } return 0;}