题意
对于一个球队有一个全名和家乡名
例如 DINAMO BYTECITY
他有两种缩写名字的方法
1.取全名的前三个字母即:DIN
2.全名的前两个字母和家乡名的第一个字母:DIB
如果有一个队伍按第二种方法取名即DIB,则其他队伍不可以通过第一种方式取名为DIN。(但可以通过第二种方法)
思路
<1>我们横容易发现上述的限制条件只针对两个全名的前三个字母相同的队伍,并且如果出现这种情况他们都不可以用第一种方式命名
<2>于是我们发现名称和队伍满足二分图的性质,于是我们可以O(N^2)的计算其最大匹配。
#include<bits/stdc++.h>
#define made(A) if(!mark[A])mark[A]=++num,R[num]=A;
#define P(a,b) G[a].push_back(b)
using namespace std;
typedef string S;
const int M=1e5+5;
map<S,int>mark;
bool use[M];
int has[2][M],T[M],n,num,cnt[M];
S A,B,N,H;
vector<int>G[M];
S R[M];
bool dfs(int x){
for(int i=0;i<G[x].size();i++){
int y=G[x][i];
if(!use[y]){
use[y]=1;
if(T[y]==-1||dfs(T[y])){
T[x]=y;T[y]=x;
return 1;
}
}
}return 0;
}
inline int LM(){
int ans=0;
memset(T,-1,sizeof(T));
for(int i=1;i<=n;i++)
if(T[i]==-1){
memset(use,0,sizeof(use));
ans+=dfs(i);
}
return ans;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;++i){
cin>>N>>H;
int a,b;
A=N.substr(0,3);
B=N.substr(0,2)+H[0];
made(A);made(B);
a=mark[A];b=mark[B];
cnt[a]++;
has[0][i]=a;
has[1][i]=b;
}
for(int i=1;i<=n;i++){
int a=has[0][i],b=has[1][i];
if(cnt[a]<=1)P(i,a+n),P(a+n,i);
P(i,b+n),P(b+n,i);
}
if(LM()==n){
puts("YES");
for(int i=1;i<=n;i++){
int t=T[i]-n;
cout<<R[t]<<endl;
}
}else puts("NO");
}