ACM/ICPC 之 有流量上下界的网络流-Dinic(可做模板)(POJ2396)
//有流量上下界的网络流 //Time:47Ms Memory:1788K #include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #include<queue> using namespace std; #define MAXC 25 #define MAXN 250 #define MAXE 100000 #define INF 0x3f3f3f3f struct Edge{ int u,v,f,next; Edge(){} Edge(int uu, int vv, int ff, int nn):u(uu), v(vv), f(ff), next(nn){} }e[MAXE]; int n, m; int S,T,s,t; int sn[MAXN], sm[MAXC]; //行和,列和 int up[MAXN][MAXC], down[MAXN][MAXC]; //上界与下界 int in[MAXN], out[MAXN]; //出入度 int h[MAXN], le; int d[MAXN]; int ans[MAXN][MAXC]; void add(int u,int v,int f) { e[le] = Edge(u, v, f, h[u]); h[u] = le++; e[le] = Edge(v, u, 0, h[v]); h[v] = le++; } bool Init() { int TT; bool result = true; scanf("%d", &TT); while(TT--){ int x, y, v; int x1,x2,y1,y2; char op[2]; scanf("%d%d%s%d", &x, &y, op, &v); if(!result) continue; x1 = x2 = x; y1 = y2 = y; if(x == 0){ x1 = 1; x2 = n;} if(y == 0){ y1 = 1; y2 = m;} for(int i = x1; i <= x2; i++) { for(int j = y1; j <= y2; j++) { if(op[0] == '='){ if(v > up[i][j] || v < down[i][j]) result = false; up[i][j] = down[i][j] = v; } else if(op[0] == '>') down[i][j] = max(down[i][j], v+1); else up[i][j] = min(up[i][j], v-1); if(up[i][j] < down[i][j]) result = false; } } } return result; } void Build() //建图 { memset(h, -1, sizeof(h)); memset(in,0,sizeof(in)); memset(out,0,sizeof(out)); le = 0; s = 0; t = n+m+1; //原图源汇点 S = t+1; T = t+2; //超级源汇点 for(int i =1; i <= n; i++) //建立初始各边 { for(int j = 1; j <= m; j++) { int x = i, y = j + n; add(x, y, up[i][j] - down[i][j]); in[y] += down[i][j]; out[x] += down[i][j]; } } for(int i = 1; i <= n; i++) //从s流出的流量 { in[i] += sn[i]; out[s] += sn[i]; } for(int i = 1; i <= m; i++) //到t的流量 { in[t] += sm[i]; out[i+n] += sm[i]; } for(int i = 0; i <= n+m+1; i++) //新建补边 { int x,y,w; if(in[i] > out[i]) { out[S] += in[i] - out[i]; add(S,i,in[i] - out[i]); } else if(in[i] < out[i]) add(i, T, out[i] - in[i]); } add(t, s, INF); } bool BFS() { memset(d, -1, sizeof(d)); queue<int> q; q.push(S); d[S] = 0; while(!q.empty()){ int cur = q.front(); q.pop(); for(int i = h[cur]; i != -1; i = e[i].next) { int v = e[i].v; if(d[v] == -1 && e[i].f) { d[v] = d[cur] + 1; if(v == T) return true; q.push(v); } } } return false; } int DFS(int x, int sum) { if (x == T || sum == 0) return sum; int src = sum; for (int i = h[x]; i != -1; i = e[i].next) { int v = e[i].v; if (d[v] == d[x] + 1 && e[i].f) { int tmp = DFS(v, min(sum, e[i].f)); e[i].f -= tmp; e[i^1].f += tmp; sum -= tmp; } } return src - sum; } int Dinic() { int maxflow = 0; while(BFS()){ maxflow += DFS(S, INF); } return maxflow; } int main() { //freopen("in.txt", "r", stdin); //freopen("out.txt", "w", stdout); int TT; scanf("%d",&TT); while(TT--){ memset(e, 0, sizeof(e)); memset(up, INF, sizeof(up)); memset(down, 0 ,sizeof(down)); scanf("%d%d", &n,&m); for(int i = 1; i <= n; i++) scanf("%d", &sn[i]); for(int i = 1; i <= m; i++) scanf("%d", &sm[i]); if(!Init()){ //预处理得到矛盾 printf("IMPOSSIBLE\n\n"); continue; } Build(); //构图 if(Dinic() != out[S]) printf("IMPOSSIBLE\n\n"); else{ for(int i = 1; i <= n; i++) for(int j = h[i]; j != -1; j = e[j].next) ans[i][e[j].v-n] = e[j^1].f + down[i][e[j].v-n]; for(int i = 1; i <= n; i++) { for(int j = 1; j < m; j++) printf("%d ", ans[i][j]); printf("%d\n", ans[i][m]); } printf("\n"); } } return 0; }
他坐在湖边,望向天空,她坐在对岸,盯着湖面