题意:给出n个人的信息,名字、特征、排名。在排名相差2的前提下,特征为testdata可以与特征为statements的组队,特征为anything可以任何一人组队;
求最多匹配对数,并将每队名字输出;
思路:构建一个二分图。ok
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 1111
int n;
int vis[N];
int link[N];
int mp[N][N];
int abss(int x) {return x>0?x:-x;}
int num1,num2;
struct node {
char name[30];
int r;
char st[20];
void input() {
scanf("%s%s%d",name,st,&r);
}
} p[N];
bool check1(int id) {
return p[id].st[0] == 's' || p[id].st[0] == 'a';
}
bool check2(int id) {
return p[id].st[0] =='t' || p[id].st[0] =='a';
}
bool ok(int i, int j)
{
if(abss(p[i].r-p[j].r)== 2)
return (check1(i)&&check2(j)) || (check1(j)&&check2(i));
return false;
}
int dfs(int u) {
for(int i=1; i<=num2; i++) {
if(mp[u][i]&&!vis[i]) {
vis[i] = 1;
if(link[i]==-1||dfs(link[i])) {
link[i]=u;
return 1;
}
}
}
return 0;
}
int get_match() {
int ans = 0;
memset(link,-1,sizeof(link));
for(int i=1; i<=num1; i++) {
memset(vis,0,sizeof(vis));
if(dfs(i))
ans++;
}
return ans;
}
int l[N],r[N];
int main() {
while(scanf("%d",&n)!=EOF){
memset(mp,0,sizeof(mp));
memset(l,0,sizeof(l));
memset(r,0,sizeof(r));
int x=0;
int y=0;
for(int i=1; i<=n; i++) {
p[i].input();
if(p[i].r%4<2) l[++x] = i;
else r[++y] = i;
}
num1= x;
num2= y;
/*
for(int i=1;i<=num1;i++) printf("%d ",l[i]);puts("");
for(int i=1;i<=num2;i++) printf("%d ",r[i]);puts("");
*/
//printf("%d %d\n",num1,num2);
for(int i=1; i<=num1; i++)
for(int j=1; j<=num2; j++) {
if(ok(l[i],r[j])) {
//printf("%d %d\n",l[i],r[j]);
mp[i][j]=1;
}
}
printf("%d\n",get_match());
for(int i=1; i<=num2; i++) {
if(link[i]!=-1) {
x = r[i];
y = l[link[i]];
if(check1(x)&&check2(y)) printf("%s %s\n",p[x].name,p[y].name);
else printf("%s %s\n",p[y].name,p[x].name);
}
}
}
}