【网络流】 HDOJ 4888 Redraw Beautiful Drawings

建图很简单,每行每列看成一个点。。原点到行点连一条流量为行值的边,列点到汇点连一条流量为列值的边。。每个行点到每个列点连一条流量为K的边。。。跑最大流,如果满流,则肯定有解。。。判断多解和唯一解很麻烦。。对于每个行点,在残余网络中dfs找能不能回到该点。。。如果能则多解,否则唯一解。。。注意dfs的时候每次走到下一点的时候不能立即走其反向边。。原理我觉得是判断行列之间的流量是否有影响,如果一点的流量能不通过其反向边流回该点,说明行列之间能通过流量调节达到平衡。。也就是说有多解。。

#include <iostream>  
#include <queue>  
#include <stack>  
#include <map>  
#include <set>  
#include <bitset>  
#include <cstdio>  
#include <algorithm>  
#include <cstring>  
#include <climits>  
#include <cstdlib>
#include <cmath>
#include <time.h>
#define maxn 805
#define maxm 400005
#define eps 1e-10
#define mod 1000000009
#define INF 99999999  
#define lowbit(x) (x&(-x))  
#define ls o<<1
#define rs o<<1 | 1
#define lson o<<1, L, mid  
#define rson o<<1 | 1, mid+1, R  
typedef long long LL;
//typedef int LL;
using namespace std;

int row[maxn], col[maxn];
struct Edge
{
	int to, cap, flow, next;
};
struct dinic
{
	int n, m, s, t, ok, uu;
	Edge e[maxm];
	int h[maxn];
	queue<int> q;
	bool vis[maxn];
	int dis[maxn];
	int cur[maxn];
	
	void init(void)
	{
		m = 2;
		memset(h, -1, sizeof h);
	}
	void add_edges(int from, int to, int cap)
	{
		e[m].next = h[from], e[m].to = to, h[from] = m, e[m].cap = cap, e[m].flow = 0, m++;
		e[m].next = h[to], e[m].to = from, h[to] = m, e[m].cap = 0, e[m].flow = 0, m++;
	}
	bool BFS(void)
	{
		memset(vis, 0, sizeof vis);
		q.push(s), dis[s] = 0, vis[s] = 1;
		while(!q.empty()) {
			int x = q.front(); q.pop();
			for(int i = h[x]; ~i; i = e[i].next) {
				if(!vis[e[i].to] && e[i].cap > e[i].flow) {
					vis[e[i].to] = 1;
					dis[e[i].to] = dis[x] + 1;
					q.push(e[i].to);
				}
			}
		}
		return vis[t];
	}
	int DFS(int x, int a)
	{
		if(x == t || a == 0) return a;
		int flow = 0, f;
		int& i = cur[x];
		if(i == 0) i = h[x];
		for(; ~i; i = e[i].next) {
			if(dis[x] + 1 == dis[e[i].to] && (f = DFS(e[i].to, min(a, e[i].cap - e[i].flow))) > 0) {
				e[i].flow += f;
				e[i^1].flow -= f;
				flow += f;
				a -= f;
				if(a == 0) break;
			} 
		}
		return flow;
	}
	int max_flow(void)
	{
		int flow = 0;
		while(BFS()) {
			memset(cur, 0, sizeof cur);
			flow += DFS(s, INF);
		}
		return flow;
	}
	void dfs(int fa, int u)
	{
		if(vis[u]) return;
		vis[u] = 1;
		if(u == uu || !ok) {
			ok = 0;
			return;
		}
		for(int i = h[u]; ~i && ok; i = e[i].next) {
			if(e[i].to == s || e[i].to == t) continue;
			if(!(e[i].cap > e[i].flow)) continue;
			if(e[i].to != fa) dfs(u, e[i].to);
		}
	}
	bool check(void)
	{
		ok = 1;
		for(int i = 1; i <= n && ok; i++) {
			memset(vis, 0, sizeof vis);
			uu = i;
			for(int j = h[i]; ~j && ok; j = e[j].next) {
				if(e[j].to == s || e[j].to == t) continue;
				if(e[j].cap > e[j].flow) dfs(i, e[j].to);
			}
		}
		if(!ok) printf("Not Unique\n");
		else printf("Unique\n");
		if(ok) return false;
		else return true;
	}
}tmp;
int n, m, k, tot;
int g[405][405];

void build(void)
{
	tmp.n = n+m+2, tmp.s = 0, tmp.t = n+m+1;
	tmp.init();
	for(int i = 1; i <= n; i++) tmp.add_edges(tmp.s, i, row[i]);
	for(int i = n+1; i <= n+m; i++) tmp.add_edges(i, tmp.t, col[i-n]);
	for(int i = 1; i <= n; i++)
		for(int j = n+1; j <= n+m; j++)
			tmp.add_edges(i, j, k);
}
void work(void)
{
	if(tot != tmp.max_flow()) {
		printf("Impossible\n");
		return;
	}
	for(int i = 1; i <= n; i++) {
		int cnt = m;
		for(int j = tmp.h[i]; ~tmp.e[j].next; j = tmp.e[j].next)
			if(tmp.e[j].cap != 0)
				g[i][cnt--] =  tmp.e[j].flow;
	}
	tmp.n = n, tmp.m = m;
	if(tmp.check()) return;
	for(int i = 1; i <= n; i++)
		for(int j = 1; j <= m; j++)
			printf("%d%c", g[i][j], j < m ? ' ' : '\n');
}
int main(void)
{
	while(scanf("%d%d%d", &n, &m, &k)!=EOF) {
		tot = 0;
		for(int i = 1; i <= n; i++) scanf("%d", &row[i]), tot += row[i];
		for(int i = 1; i <= m; i++) scanf("%d", &col[i]);
		build();
		work();
	}
	return 0;
}


你可能感兴趣的:(HDU)