codevs 1027 姓名与ID

1027 姓名与ID

 

 时间限制: 1 s
 空间限制: 128000 KB
 题目等级 : 大师 Master
 
 
题目描述 Description

有N个人,各自有一个姓名和ID(别名)。每个人的姓名和ID都没有重复。这些人依次进入一间房间,然后可能会离开。过程中可以得到一些信息,告知在房间里的某个人的ID。你的任务是准确地确定每个人的ID。

输入描述 Input Description

第一行是整数N,表示N个人,N<=20。

接下来的一行是N个人的ID,用一个空格分隔。

接下来的若干行是过程的记录:一个字母和一个字符串。字母是E、L或M中的一个。E表示进入房间,后面跟的字符串表示进来的人的姓名;L表示离开房间,后面跟的字符串表示离开的人的姓名;M表示回答询问,后面跟的字符串表示:当前用这个ID人在房间里面。

最后一行Q表示结束。

所有的姓名和ID都由不超过20个的小写字母组成。所有姓名都会在记录中出现。

一开始时,房间时空的。

输出描述 Output Description

共N行,每行形如:“姓名:ID”,如果ID不能确定,输出???。

按照姓名的字典顺序输出。

样例输入 Sample Input

7

bigman mangler sinbad fatman bigcheese frenchie capodicapo

E mugsy

E knuckles

M bigman

M mangler

L mugsy

E clyde

E bonnie

M bigman

M fatman

M frenchie

L clyde

M fatman

E ugati

M sinbad

E moriarty

E booth

Q

样例输出 Sample Output

bonnie:fatman

booth:???

clyde:frenchie

knuckles:bigman

moriarty:???

mugsy:mangler

ugati:sinbad

 

数据范围及提示 Data Size & Hint

 

/*
什么都没用结果得了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;
}

 

posted @ 2016-08-11 11:31  岂是蓬蒿人  阅读(320)  评论(0编辑  收藏  举报