练习匈牙利算法
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <queue>
#include <stack>
#include <algorithm>
#include <cmath>
using namespace std;
#define F(i, n) for (int i=0;i<(n);++i)
#define LBIT(x) x&-x
long long gcd(long long a, long long b) {
return b == 0 ? a : gcd(b, a % b);
}
template<class T>
void myswap(T * a, T * b) {
T tmp = *a;
*a = *b;
*b = tmp;
}
#define MAXN 305
#define MAXP 105
template<class T>
class myvector {
public:
myvector():_size(0){};
int size() const {
return _size;
}
void clear() {
_size = 0;
}
void push_back(T elem) {
_buf[_size++] = elem;
}
T operator [] (int index) const {
return _buf[index];
}
private:
int _size;
T _buf[MAXN + 1];
};
int n, p;
myvector<int> g[MAXP + 1];
int from[MAXN + 1];
int vis[MAXN + 1];
bool match(int x) {
int len = g[x].size();
int node;
F(i, len)
if (!vis[g[x][i]]) {
node = g[x][i];
vis[node] = 1;
if (from[node] == -1 || match(from[node])) {
from[node] = x;
return true;
}
}
return false;
}
int main()
{
freopen("input.in", "r", stdin);
int cases;
int tmp;
int cnt;
int ans;
bool flag;
scanf("%d", &cases);
F(i, cases) {
scanf("%d%d", &p, &n);
F(j, MAXP)
g[j].clear();
F(j, p) {
scanf("%d", &cnt);
F(k, cnt) {
scanf("%d", &tmp);
--tmp;
g[j].push_back(tmp);
}
}
// check
flag = true;
F(k, p)
if (!g[k].size()) {
flag = false;
break;
}
if (!flag || n < p) {
printf("NO\n");
continue;
}
// 匈牙利算法找最大匹配
ans = 0;
memset(from, -1, sizeof(from));
F(k, p) {
memset(vis, 0, sizeof(vis));
if (match(k))
++ans;
}
#if DEBUG
printf("----------------\n");
F(k, p) {
printf("%d: ", g[k].size());
F(r, g[k].size())
printf("%d ", g[k][r]);
printf("\n");
}
printf("\n");
printf("----------------\n");
printf("----------------\n");
F(k, n)
printf("%d ", from[k]);
printf("\n");
printf("----------------\n");
#endif
if (ans == p)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
hopcroft-karp 算法
/*
*二分图 hopcroft-karp 算法
*/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <queue>
#include <stack>
#include <algorithm>
using namespace std;
#define F(i, n) for (int i=0;i<(n);++i)
#define REP(i, s, t) for(int i = (s);i <= (t);++i)
#define LBIT(x) x&-x
#define MAXL 100
#define MAXR 300
#define MAXM 30000
int n1; // 左边点数
int dx[MAXL + 5];
int dy[MAXR + 5];
int mx[MAXL + 5];
int my[MAXR + 5];
bool vis[MAXL + MAXR + 5];
//vector<int> g[MAXL + 5];
int p, n;
class G {
public:
G() {clear();}
int getHead(int index) {
if (index <= MAXL )
return head[index];
else
return head[index - MAXL];
}
int getNext(int edge) {
return next[edge];
}
int getTov(int edge) {
int ret = tov[edge];
if (ret > MAXL)
ret -= MAXL;
return ret;
}
void link(int u, int v) {
++tot;
v += MAXL;
next[tot] = head[u];
tov[tot] = v;
head[u] = tot;
}
void clear() {
tot = 0;
memset(head, 0, sizeof(head));
}
private:
int tot;
int head[MAXL + MAXR + 5];
int next[MAXM + 5];
int tov[MAXM + 5];
};
class myque{
public:
void push(int elem) {
_buf[t++] = elem;
}
void pop() {
++s;
}
int front() {
return _buf[s];
}
void clear() {
s = 0;
t = 0;
}
bool empty() {
return s == t;
}
private:
int s;
int t;
int _buf[1005];
};
G gg;
//queue<int> que;
myque que;
bool find(int u) {
for (int edge = gg.getHead(u);edge;edge = gg.getNext(edge) ) {
int v = gg.getTov(edge);
if (!vis[v] && dy[v] == dx[u] + 1) {
vis[v] = true;
if ( !my[v] || find(my[v]) ) {
my[v] = u;
mx[u] = v;
return true;
}
}
}
return false;
}
int main()
{
freopen("input.in", "r", stdin);
//freopen("output.out", "w", stdout);
int cases;
int ans;
scanf("%d", &cases);
F(ncases, cases) {
scanf("%d%d", &p, &n);
gg.clear();
REP(i, 1, p) {
int num, tmp;
scanf("%d", &num);
F(j, num) {
scanf("%d", &tmp);
gg.link(i, tmp);
}
}
#ifdef DEBUG
REP(i, 1, p) {
for (int edge = gg.getHead(i);edge;edge = gg.getNext(edge) ) {
int v = gg.getTov(edge);
printf("%d ", v);
}
printf("\n");
}
#endif
bool ff = true;
REP(i, 1, p)
if( gg.getHead(i) == 0) {
ff = false;
break;
}
if (!ff || n < p) {
printf("NO\n");
continue;
}
memset(mx, 0, sizeof(mx));
memset(my, 0, sizeof(my));
ans = 0;
while(true) {
bool flag = false;
memset(dx, 0, sizeof(dx));
memset(dy, 0, sizeof(dy));
//while(!que.empty()) que.pop();
que.clear();
REP(i, 1, p)
if (!mx[i])
que.push(i);
while( !que.empty() ) {
int u = que.front();
que.pop();
//cout << "fuck: " << g[i].size() << endl;
for (int edge = gg.getHead(u);edge;edge = gg.getNext(edge) ) {
int v = gg.getTov(edge);
if ( !dy[v] ) {
dy[v] = dx[u] + 1;
if ( my[v] ) {
dx[my[v]] = dy[v] + 1;
que.push(my[v]);
} else
flag = true;
}
}
}
if (!flag)
break;
memset(vis, false, sizeof(vis));
REP(i, 1, p)
if (!mx[i] && find(i))
++ans;
}
if (ans < p)
printf("NO\n");
else
printf("YES\n");
}
return 0;
}