http://wikioi.com/problem/1027/
恶心的字符串!!!
一道二分图匹配
第一行是整数N,表示N个人,N<=20。
接下来的一行是N个人的ID,用一个空格分隔。
接下来的若干行是过程的记录:一个字母和一个字符串。字母是E、L或M中的一个。E表示进入房间,后面跟的字符串表示进来的人的姓名;L表示离开房间,后面跟的字符串表示离开的人的姓名;M表示回答询问,后面跟的字符串表示:当前用这个ID人在房间里面。
最后一行Q表示结束。
所有的姓名和ID都由不超过20个的小写字母组成。所有姓名都会在记录中出现。
一开始时,房间时空的。
注意字母后跟的是什么!!!
E进入后标记,M后的id在房间,那么这个人就可能用这个ID(多连点没关系,但一定要对)
答案是这个人肯定配这个ID(不配这个Id就没的配了)
#include<iostream>
#include<cstring>
#include<map>
#include<string>
#include<algorithm>
using namespace std;
int clock_vis;
map<string,int> Name;//map 可以开字符串的标志
map<string,int> ID;
string P[25],Q[25]; //字符串数组
bool Map[25][25];
int con[25];
bool Visited[25];
int wr[25];
bool In[25];
int n;
bool find(int x)//二分图匹配
{
for (int i=1;i<=n;i++)
if (wr[i]!=clock_vis&&Map[x][i])
{
wr[i]=clock_vis;
if (!con[i]||find(con[i]))
{
con[i]=x;
return 1;
}
}
return 0;
}
bool Check(int x)//检查
{
if (Visited[x]) return 0;
Visited[x]=1;
for (int i=1;i<=n;i++)
if (!wr[i]&&Map[x][i]&&con[i]!=x)//当前没配的&&可以配&&i原配不是X
{
wr[i]=1;
if (!con[i]||!Check(con[i])) return 0;//换一个配方案可行
}
return 1;
}
int main()
{
memset(Map,1,sizeof(Map));
cin>>n;
for (int i=1;i<=n;i++)
{
string s;
cin>>s;
ID[s]=i;
Q[i]=s;
}
int l=0;
while (1)
{
char w; string s;
cin>>w>>s;
if (w=='Q') break;
if (w=='E')
{
if (Name.count(s)==0) //没出现过
{
P[l]=s;
Name[s]=++l;//个数++
}
In[Name[s]]=1;
}
if (w=='L') In[Name[s]]=0;
if (w=='M')
for (int i=1;i<=n;i++)
if (!In[i]) Map[i][ID[s]]=0;//如果不在就没边
}
sort(P,P+n);//直接字符串排序
memset(con,0,sizeof(con));
memset(wr,0,sizeof(wr));
for (int i=1;i<=n;i++)
{
clock_vis=i;
find(i);
}
for (int i=0;i<n;i++)
{
memset(Visited,0,sizeof(Visited));
memset(wr,0,sizeof(wr));
cout<<P[i]<<":";
if (Check(Name[P[i]]))
{
for (int j=1;j<=n;j++)
if (con[j]==Name[P[i]]) cout<<Q[j]<<endl;
}
else cout<<"???"<<endl;
}
return 0;
}