只看最后两段就行了。。
题意就是,有些会statement,有些人会testdata,有些人两种都会。然后每个人有一个rank值,rank值相差2的两个人可以合作,求最大匹配。
题意就是,有些会statement,有些人会testdata,有些人两种都会。然后每个人有一个rank值,rank值相差2的两个人可以合作,求最大匹配。
注意rank值相差2的人可以相互合作,也就是说,我们要把图分成二分图,使得能跟左边任意一个节点配对的点一定在右边。这样只需将rank % 4 < 2的人放在左边节点,rank % 4 >= 2的人放在右边节点就行了。
#include<functional>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<cmath>
#include<map>
#include<set>
#define REP(i, n) for(int i=0; i<n; i++)
#define CLR(a, b) memset(a, b, sizeof(a))
#define PB push_back
#define LL long long
using namespace std;
const int maxn = 1111;
struct Person
{
string name, like;
int rank;
}p[maxn];
int n, l[maxn], r[maxn];
bool check1(int id)
{
return p[id].like == "statements" || p[id].like == "anything";
}
bool check2(int id)
{
return p[id].like == "testdata" || p[id].like == "anything";
}
bool ok(int i, int j)
{
if(abs(p[i].rank-p[j].rank) == 2) return (check1(i)&&check2(j)) || (check1(j)&&check2(i));
return false;
}
struct BPM
{
bool g[maxn][maxn], vis[maxn];
int _left[maxn], n, m;
void init(int n, int m)
{
this->n = n;
this->m = m;
CLR(g, 0);
}
bool dfs(int u)
{
REP(v, m) if(!vis[v] && g[u][v])
{
vis[v] = 1;
if(_left[v] == -1 || dfs(_left[v]))
{
_left[v] = u;
return true;
}
}
return false;
}
int solve()
{
CLR(_left, -1);
int ret = 0;
REP(i, n)
{
CLR(vis, 0);
if(dfs(i)) ret++;
}
return ret;
}
void print()
{
printf("%d\n", solve());
REP(i, m) if(_left[i] != -1)
{
int x = r[i], y = l[_left[i]];
if(check1(x) && check2(y)) cout<<p[x].name<<' '<<p[y].name<<endl;
else cout<<p[y].name<<' '<<p[x].name<<endl;
}
}
}solver;
int main()
{
while(~scanf("%d", &n))
{
REP(i, n) cin>>p[i].name>>p[i].like>>p[i].rank;
int x = 0, y = 0;
REP(i, n)
{
if(p[i].rank % 4 < 2) l[x++] = i;
else r[y++] = i;
}
solver.init(x, y);
REP(i, x) REP(j, y) if(ok(l[i], r[j])) solver.g[i][j] = 1;
solver.print();
}
return 0;
}