题目:
http://acm.hust.edu.cn/vjudge/contest/view.action?cid=93936#problem/E
题意:
给出n个家庭的人数,m个房子的容纳人数,两个家庭的总人数等于房子的容纳人数,则可以入住,求出可以入住的最多的家庭对。
思路:
一般图求最大匹配不可以用 二分图,要用 一般图匹配带花树。
。。。(这道题的数据水了。。。
AC.
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <set>
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 405;
int N;
bool graph[maxn][maxn], Inqueue[maxn], Inpath[maxn], Inblossom[maxn];
int Match[maxn];
int Head, Tail;
int Queue[maxn];
int Start, Finish;
int Newbase;
int Father[maxn], Base[maxn];
int Count;
void Push(int u)
{
Queue[Tail] = u;
Tail++;
Inqueue[u] = 1;
}
int Pop()
{
int res = Queue[Head];
Head++;
return res;
}
int FindComAnc(int u, int v)
{
memset(Inpath, 0, sizeof(Inpath));
while(1) {
u = Base[u];
Inpath[u] = 1;
if(u == Start) break;
u = Father[Match[u]];
}
while(1) {
v = Base[v];
if(Inpath[v]) break;
v = Father[Match[v]];
}
return v;
}
void ResetTrae(int u)
{
int v;
while(Base[u] != Newbase) {
v = Match[u];
Inblossom[Base[u]] = Inblossom[Base[v]] = 1;
u = Father[v];
if(Base[u] != Newbase) Father[u] = v;
}
}
void BloosomContract(int u, int v)
{
Newbase = FindComAnc(u, v);
memset(Inblossom, 0, sizeof(Inblossom));
ResetTrae(u);
ResetTrae(v);
if(Base[u] != Newbase) Father[u] = v;
if(Base[v] != Newbase) Father[v] = u;
for(int tu = 1; tu <= N; ++tu) {
if(Inblossom[Base[tu]]) {
Base[tu] = Newbase;
if(!Inqueue[tu]) Push(tu);
}
}
}
void FindAugmentingPath()
{
memset(Inqueue, 0, sizeof(Inqueue));
memset(Father, 0, sizeof(Father));
for(int i = 1; i <= N; ++i) {
Base[i] = i;
}
Head = Tail = 1;
Push(Start);
Finish = 0;
while(Head < Tail) {
int u = Pop();
for(int v = 1; v <= N; ++v) {
if(graph[u][v] && (Base[u] != Base[v]) && (Match[u] != v)) {
if((v == Start) || (Match[v] > 0) && Father[Match[v]] > 0) {
BloosomContract(u, v);
}
else if(Father[v] == 0) {
Father[v] = u;
if(Match[v] > 0)
Push(Match[v]);
else {
Finish = v;
return;
}
}
}
}
}
}
void AugmentPath()
{
int u, v, w;
u = Finish;
while(u > 0) {
v = Father[u];
w = Match[v];
Match[v] = u;
Match[u] = v;
u = w;
}
}
void Edmonds()
{
memset(Match, 0, sizeof(Match));
for(int u = 1; u <= N; ++u) {
if(Match[u] == 0) {
Start = u;
FindAugmentingPath();
if(Finish > 0) AugmentPath();
}
}
}
void PrintMatch()
{
Count = 0;
for(int u = 1; u <= N; ++u) {
if(Match[u] > 0) Count++;
}
printf("%d\n", Count/2);
}
int val[maxn];
set<int> s;
int main()
{
//freopen("in", "r", stdin);
int T;
scanf("%d", &T);
while(T--) {
s.clear();
memset(graph, 0, sizeof(graph));
int m;
scanf("%d%d", &N, &m);
for(int i = 1; i <= N; ++i) {
scanf("%d", &val[i]);
}
for(int i = 1; i <= m; ++i) {
int h;
scanf("%d", &h);
s.insert(h);
}
for(int i = 1; i <= N; ++i) {
for(int j = i+1; j <= N; ++j) {
if(s.find(val[i] + val[j]) != s.end()) {
graph[i][j] = graph[j][i] = 1;
}
}
}
Edmonds();
PrintMatch();
}
return 0;
}