[网络流] HDOJ 5457 Hold Your Hand

建出字典树,然后做最小割就行了...

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;

const int maxn = 5005;
const int maxm = 400005;
const int INF = 0x3f3f3f3f;

struct Edge
{
	int v, c, next;
	Edge() {}
	Edge(int v, int c, int next) : v(v), c(c), next(next) {}
}E[maxm];

struct node
{
	int id, val;
	node *lson, *rson;
}pool[maxm], *tail, *rootA, *rootB;

queue<int> q;
int H[maxn], cntE;
int dis[maxn];
int cur[maxn];
int cnt[maxn];
int pre[maxn];
int n, m, s, t, flow, nv;

void addedges(int u, int v, int c)
{
	E[cntE] = Edge(v, c, H[u]);
	H[u] = cntE++;
	E[cntE] = Edge(u, 0, H[v]);
	H[v] = cntE++;
}

void bfs()
{
	memset(cnt, 0, sizeof cnt);
	memset(dis, -1, sizeof dis);
	cnt[0]++, dis[t] = 0;
	q.push(t);
	while(!q.empty()) {
		int u = q.front();
		q.pop();
		for(int e = H[u]; ~e; e = E[e].next) {
			int v = E[e].v;
			if(dis[v] == -1) {
				dis[v] = dis[u] + 1;
				cnt[dis[v]]++;
				q.push(v);
			}
		}
	}
}

int isap()
{
	memcpy(cur, H, sizeof cur);
	bfs();
	flow = 0;
	int u = pre[s] = s, f, minv, e, pos;
	while(dis[s] < nv) {
		if(u == t) {
			f = INF;
			for(int i = s; i != t; i = E[cur[i]].v) if(f > E[cur[i]].c) {
				f = E[cur[i]].c;
				pos = i;
			}
			for(int i = s; i != t; i = E[cur[i]].v) {
				E[cur[i]].c -= f;
				E[cur[i] ^ 1].c += f;
			}
			flow += f;
			u = pos;
		}
		for(e = cur[u]; ~e; e = E[e].next) if(E[e].c && dis[E[e].v] + 1 == dis[u]) break;
		if(~e) {
			cur[u] = e;
			pre[E[e].v] = u;
			u = E[e].v;
		}
		else {
			if(--cnt[dis[u]] == 0) break;
			for(minv = nv, e = H[u]; ~e; e = E[e].next) if(E[e].c && minv > dis[E[e].v]) {
				minv = dis[E[e].v];
				cur[u] = e;
			}
			dis[u] = minv + 1;
			cnt[dis[u]]++;
			u = pre[u];
		}
	}
	return flow;
}

void init()
{
	cntE = 0;
	memset(H, -1, sizeof H);
	for(node *p = pool; p < tail; p++) p->val = INF;
}

node* newnode()
{
	tail->id = tail - pool;
	tail->lson = tail->rson = NULL;
	return tail++;
}

node* dfs(int pos)
{
	if(pos == 0) return NULL;
	node *p = newnode();
	p->lson = dfs(pos-1);
	p->rson = dfs(pos-1);
	return p;
}

void _ini()
{
	tail = pool;
	rootA = newnode();
	rootA->lson = dfs(8);
	rootA->rson = dfs(8);
	
	rootB = newnode();
	rootB->lson = dfs(8);
	rootB->rson = dfs(8);
	
	s = rootA->id, t = rootB->id;
	nv = tail - pool;
}

void DFS(node *p, int flag)
{
	if(p->lson) {
		if(flag == 0) addedges(p->id, p->lson->id, p->lson->val);
		else addedges(p->lson->id, p->id, p->lson->val);
		DFS(p->lson, flag);
	}
	if(p->rson) {
		if(flag == 0) addedges(p->id, p->rson->id, p->rson->val);
		else addedges(p->rson->id, p->id, p->rson->val);
		DFS(p->rson, flag);
	}
}

char ss[100], op[100];
int a[300], b[300];

void work()
{
	int n, m;
	scanf("%d%d", &n, &m);
	for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
	for(int i = 1; i <= m; i++) {
		int val;
		scanf("%s%s%d", op, ss, &val);
		if(op[0] == 'P') {
			node *p = rootA;
			for(int j = 0; ss[j]; j++) {
				if(ss[j] == '0') p = p->lson;
				else p = p->rson;
			}
			p->val = min(p->val, val);
		}
		else {
			node *p = rootB;
			int len = strlen(ss);
			for(int j = len-1; j >= 0; j--) {
				if(ss[j] == '0') p = p->lson;
				else p = p->rson;
			}
			p->val = min(p->val, val);
		}
	}
	
	DFS(rootA, 0);
	DFS(rootB, 1);
	
	for(int i = 1; i <= n; i++) {
		for(int j = 1; j <= 8; j++) {
			b[j] = a[i] % 2;
			a[i] /= 2;
		}
		
		int t1, t2;
		node *p = rootA;
		for(int j = 8; j >= 1; j--) {
			if(b[j]) p = p->rson;
			else p = p->lson;
		}
		t1 = p->id;
		
		p = rootB;
		for(int j = 1; j <= 8; j++) {
			if(b[j]) p = p->rson;
			else p = p->lson;
		}
		t2 = p->id;
		
		addedges(t1, t2, INF);
	}
	
	int ans = isap();
	
	if(ans >= INF) printf("-1\n");
	else printf("%d\n", ans);
}

int main()
{
	_ini();
	int _;
	scanf("%d", &_);
	for(int i = 1; i <= _; i++) {
		init();
		printf("Case #%d: ", i);
		work();
	}

	return 0;
}


你可能感兴趣的:(网络流)