/*
什么都没用结果得了90分
求错误在那??????
正解 二分图匹配 在下面
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<map>
#include<algorithm>
using namespace std;
int n,tot,topt,g[50],a[50][50],sum[50];
string s[50];
string ss[50];
map<string,int>p;
map<string,int>f;
queue<int>q;
struct node
{
string xingming;
string ID;
}fin[50];
int cmp(node x,node y)
{
return x.xingming<y.xingming;
}
int main()
{
int i,j,k;
cin>>n;
for(i=1;i<=n;i++)
{
cin>>s[i];
sum[i]=n;
f[s[i]]=i;
}
char c;
while(1)
{
cin>>c;
if(c==‘Q‘)break;
if(c==‘E‘)
{
string st;
cin>>st;
if(p[st]==0)
{
ss[++tot]=st;
p[st]=tot;
}
g[p[st]]=1;
}
if(c==‘L‘)
{
string st;
cin>>st;
g[p[st]]=0;
}
if(c==‘M‘)
{
string st;
cin>>st;
int t=f[st];
for(i=1;i<=n;i++)
{
if(i>tot||g[i]==0||a[i][t]==1)
{
if(a[i][t]==0)sum[t]--;
a[i][t]=1;
}
}
}
}
for(i=1;i<=n;i++)
if(sum[i]==1)
q.push(i);
while(!q.empty())
{
int d=q.front();
q.pop();
for(i=1;i<=n;i++)
if(a[i][d]==0)
{
for(j=1;j<=n;j++)
if(j!=d)
{
if(a[i][j]==0)
{
sum[j]--;
if(sum[j]==1)q.push(j);
}
a[i][j]=1;
}
}
}
for(i=1;i<=n;i++)
{
fin[i].xingming=ss[i];
int flag=0;
for(j=1;j<=n;j++)
if(a[i][j]==0&&sum[j]==1)
{
fin[i].ID=s[j];
flag=1;
}
if(flag==0)fin[i].ID="???";
}
sort(fin+1,fin+n+1,cmp);
for(i=1;i<=n;i++)
cout<<fin[i].xingming<<":"<<fin[i].ID<<endl;
return 0;
}
/*
二分图匹配
刚开始每个人和每个ID都连一条边 刚开始都有可能
有一个数组记录是否在房间内 当E和L操作时更新此数组
当M时 把此时的ID和不在房间内的人边取消掉
结束后
把现在还连着的边取消掉 看看是否能完没匹配
若不能 则说明这条边应该连 记录这条边两边的姓名与ID
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<map>
#include<algorithm>
using namespace std;
int n,tot,topt,g[50],a[50][50],match[50],ff[50];
string s[50];
string ss[50];
map<string,int>p;
map<string,int>f;
queue<int>q;
struct node
{
string xingming;
string ID;
}fin[50];
int cmp(node x,node y)
{
return x.xingming<y.xingming;
}
int dfs(int x)
{
for(int i=1;i<=n;i++)
{
if(a[x][i]==0&&!ff[i])
{
ff[i]=1;
if(!match[i]||dfs(match[i]))
{
match[i]=x;
return 1;
}
}
}
return 0;
}
int main()
{
int i,j,k;
cin>>n;
for(i=1;i<=n;i++)
{
cin>>s[i];
f[s[i]]=i;
}
char c;
while(1)
{
cin>>c;
if(c==‘Q‘)break;
if(c==‘E‘)
{
string st;
cin>>st;
if(p[st]==0)
{
ss[++tot]=st;
p[st]=tot;
}
g[p[st]]=1;
}
if(c==‘L‘)
{
string st;
cin>>st;
g[p[st]]=0;
}
if(c==‘M‘)
{
string st;
cin>>st;
int t=f[st];
for(i=1;i<=n;i++)
if(g[i]==0)
a[i][t]=1;
}
}
for(i=1;i<=n;i++)
{
int flag=0;
fin[i].xingming=ss[i];
for(j=1;j<=n;j++)
if(a[i][j]==0)
{
a[i][j]=1;
int sum=0;
memset(match,0,sizeof(match));
for(k=1;k<=n;k++)
{
memset(ff,0,sizeof(ff));
if(dfs(k))
sum++;
}
if(sum<n)
{
fin[i].ID=s[j];
flag=1;
a[i][j]=0;
break;
}
a[i][j]=0;
}
if(!flag)fin[i].ID="???";
}
sort(fin+1,fin+n+1,cmp);
for(i=1;i<=n;i++)
cout<<fin[i].xingming<<":"<<fin[i].ID<<endl;
return 0;
}