一道很基础的网络流建模。。
本题输入的是前缀和,先用它们求出每行、每列的元素和
然后将每一行看作一个节点(记作Xi),每一列看作一个节点(记作Yi),并新增源点S、汇点T。
S往Xi连边,容量为这一行的元素和减1;
Yi往T连边,容量同上。
每个Xi往每个Yj连边,容量为20-1=19。
之所以要将容量都减1,是因为边权要在1~20之间,有下界,但并不需要用到专门的有下界最大流算法,可以直接先减1,求出结果后再加1。
跑一遍最大流。当且仅当所有S出边和T入边都满载时有解。元素Aij的值即为Xi -> Yj的流量+1。
模板用的是Rujia Liu的。。可读性很强,但效率不是很高。。下次把黄学长的模板学过来。。
(最近刷题速度下降。。再这样下去药丸。。
// UVa11082 #include <cstdio> #include <algorithm> #include <cstring> using namespace std; const int M=2000, N=100, INF=0x3f3f3f3f; #define rep(i,a,b) for (int i=a; i<=b; i++) #define read(x) scanf("%d", &x) struct Edge{ int from, to, pre, cap, flow; }e[M]; int p, pre[N]; void ine(int from, int to, int cap, int flow) { e[p].from=from; e[p].to=to; e[p].cap=cap; e[p].pre=pre[from]; e[p].flow=flow; pre[from]=p; p++; } #define reg(i,x) for (int i=pre[x]; i!=-1; i=e[i].pre) void Add_Edge(int from, int to, int cap) { ine(from, to, cap, 0); ine(to, from, 0, 0); } int n, m, s, t, a[N], last, tot, edges, nodes, id[N][N], kase=0, T, cur[N], d[N]; bool vis[N]; void init() { p=0; rep(i,1,edges) e[i].pre=-1; rep(i,1,nodes) pre[i]=-1; } int Q[2*N]; bool BFS() { memset(vis, 0, sizeof(vis)); int head=1, tail=1; Q[1]=s; d[s]=0; vis[s]=true; while (head<=tail) { int x=Q[head++]; reg(i,x) { int y=e[i].to; if (!vis[y] && e[i].cap>e[i].flow) { vis[y]=true; d[y]=d[x]+1; Q[++tail]=y; } } } return vis[t]; } int DFS(int x, int a) { // a表示“目前为止所有弧的最小残量” if (x==t || a==0) return a; int flow=0, f; for (int &i=cur[x]; i!=-1; i=e[i].pre) { if (d[x]+1==d[e[i].to] && (f=DFS(e[i].to, min(a, e[i].cap-e[i].flow)))>0) { flow+=f; a-=f; // Why can we do this? e[i].flow+=f; e[i^1].flow-=f; if (a==0) break; } } return flow; } void Dinic() { int flow=0; while (BFS()) { rep(i,1,n+m+2) cur[i]=pre[i]; flow+=DFS(s, INF); } } int main() { read(T); while (T--) { read(n); read(m); edges=n*m*2+n+m+5; nodes=n+m+5; init(); read(tot); a[1]=tot; rep(i,2,n) last=tot, read(tot), a[i]=tot-last; read(tot); a[n+1]=tot; rep(i,n+2,n+m) last=tot, read(tot), a[i]=tot-last; s=n+m+1, t=n+m+2; rep(i,1,n) Add_Edge(s, i, a[i]-m); rep(i,n+1,m+n) Add_Edge(i, t, a[i]-n); rep(i,1,n) rep(j,n+1,n+m) { Add_Edge(i, j, 19); id[i][j]=p-2; } Dinic(); printf("Matrix %d ", ++kase); rep(i,1,n) { rep(j,n+1,n+m) printf("%d ", e[id[i][j]].flow+1); puts(""); } puts(""); } return 0; }