BZOJ 2744: [HEOI2012]朋友圈

无向图的最大团可以转化为补图的最大独立集,而对于B的补图是一个二分图,二分图的最大独立集等于顶点数减去最小点覆盖,而最小点覆盖又等于最大匹配,那么就是求B图的最大匹配
而A图要求选一个奇数一个偶数,那么最多就只能选两个
暴力枚举选哪些,再在B图上跑匈牙利,用时间戳优化,就不用每次都memset了

#include <bits/stdc++.h>
#define pb push_back
#define fi first
#define se second
#define pii pair<int, int>
#define lp p << 1
#define rp p << 1 | 1
#define mid ((l + r) >> 1)
#define ll long long
#define db double
#define rep(i,a,b) for(int i=a;i<b;i++)
#define per(i,a,b) for(int i=b-1;i>=a;i--)
#define Edg int ccnt=1,head[N],to[E],ne[E];void addd(int u,int v){to[++ccnt]=v;ne[ccnt]=head[u];head[u]=ccnt;}void add(int u,int v){addd(u,v);addd(v,u);}
#define Edgc int ccnt=1,head[N],to[N * 2],ne[N*2],c[N*2];void addd(int u,int v,int w){to[++ccnt]=v;ne[ccnt]=head[u];c[ccnt]=w;head[u]=ccnt;}void add(int u,int v,int w){addd(u,v,w);addd(v,u,w);}
#define es(u,i,v) for(int i=head[u],v=to[i];i;i=ne[i],v=to[i])
const int MOD = 1e9 + 9;
void M(int &x) {if (x >= MOD)x -= MOD; if (x < 0)x += MOD;}
int qp(int a, int b = MOD - 2) {int ans = 1; for (; b; a = 1LL * a * a % MOD, b >>= 1)if (b & 1)ans = 1LL * ans * a % MOD; return ans % MOD;}
int gcd(int a, int b) { while (b) { a %= b; std::swap(a, b); } return a; }

char buf[1 << 21], *p1 = buf, *p2 = buf;
inline char getc() {
    return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++;
}
inline int _() {
    int x = 0, f = 1; char ch = getc();
    while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getc(); }
    while (ch >= '0' && ch <= '9') { x = x * 10ll + ch - 48; ch = getc(); }
    return x * f;
}

const int N = 3e3 + 15;
const int E = N * N + 7;
Edg
int a[N], b[N], m, n, q, ban[N], vis[N], match[N], match_time[N], ban_time, vis_time;
bool mp[N][N], linked[N][N];

int hungry(int u) {
	if (ban[u] == ban_time) return 0;
	es(u, i, v) {
		if (ban[v] != ban_time && vis[v] != vis_time) {
			vis[v] = vis_time;
			if (!match[v] || match_time[v] != ban_time || hungry(match[v])) {
				match_time[v] = ban_time;
				match[v] = u;
				return 1;
			}
		}
	}
	return 0;
}

int solve(int x = 0, int y = 0) {
	ban_time++;
	int ans = 0;
	rep (i, 1, n + 1) {
		if (!mp[x][i] || !mp[y][i]) {
			ban[i] = ban_time;
			ans++;
		}
	}
	rep (i, 1, n + 1) {
		vis_time++;
		ans += hungry(i);
	}
	return n - ans;
}

int main() {
	m = _(), n = _(), q = _();
	rep (i, 1, m + 1) a[i] = _();
	rep (i, 1, n + 1) b[i] = _(), mp[0][i] = 1;
	rep (i, 1, n + 1) if (b[i] & 1)
		rep (j, 1, n + 1) if ((~b[j] & 1) && (__builtin_popcount(b[i] | b[j]) % 2 == 0)) {
			addd(i, j);
		}
	rep (i, 0, q) {
		int x = _(), y = _();
		mp[x][y] = 1;
	}
	int ans = solve();
	rep (i, 1, m + 1) ans = std::max(ans, solve(i) + 1);
	rep (i, 1, m + 1) if (a[i] & 1)
		rep (j, i + 1, m + 1) if (~a[j] & 1) 
			ans = std::max(ans, solve(i, j) + 2);
	printf("%d\n", ans);
}
posted @ 2020-02-23 22:26  Mrzdtz220  阅读(81)  评论(0)    收藏  举报