标签:
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 2600 | Accepted: 933 |
Description
Input
Output
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
【题意】一个犯罪团伙有N个人,他们分别有一个名字和一个网名 现已知他们会先后进出一个房间发送电报 警方可以知道所有时间下: 进出房间的人的真实名字 同时通过截获该房间发出的电报,获得网名 问最后
能否将所有真实名字和虚拟网名对上
【分析】首先根据题目条件名字和网名是一一对应的,可以大概确定是二分匹配中的完美匹配 然而根据样例很容易看出来,要想根据正确关系来建边是很复杂的 容易的做法是:每次将不可能匹配的名字和网名建边,
最后根据补图进行最大匹配即可初步得出所有匹配关系.但现在得到的最大匹配不一定是完美匹配 要确定某个名字和网名是匹配的 我们可以删除当前已匹配的边,再进行最大匹配 如果结果减小了,则一定是对应的
这样,依次枚举每一条最大匹配中的边.即可得出答案
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <cmath> #include <string> #include <map> #include <queue> #include <vector> #define inf 0x7fffffff #define met(a,b) memset(a,b,sizeof a) typedef long long ll; using namespace std; const int N = 35; const int M = 5005; int read() { int x=0,f=1; char c=getchar(); while(c<‘0‘||c>‘9‘) { if(c==‘-‘)f=-1; c=getchar(); } while(c>=‘0‘&&c<=‘9‘) { x=x*10+c-‘0‘; c=getchar(); } return x*f; } struct man { string a,b; } s[N]; map<string,int>m1,m2; string s1[N]; int edg[N][N]; int link[N],vis[N]; int mark[N]; int id,n; void init() { memset(edg,0,sizeof(edg)); memset(mark,0,sizeof(mark)); id=1; m1.clear(),m2.clear(); } bool cmp(man x,man y) { return x.a<y.a; } bool dfs(int u) { for(int i=1; i<=n; i++) { if(!vis[i]&&edg[u][i]==0) { vis[i]=1; if(link[i]==-1||dfs(link[i])) { link[i]=u; return true; } } } return false; } int MaxMatch() { memset(link,-1,sizeof(link)); int ans=0; for(int i=1; i<=n; i++) { memset(vis,0,sizeof(vis)); if(dfs(i)) ans++; } return ans; } int main() { int m,a,b,d; char ch; string str; while(~scanf("%d",&n)) { init(); for(int i=1; i<=n; i++) { cin>>s1[i]; m1[s1[i]]=i; } while(cin>>ch) { if(ch==‘Q‘) break; else { cin>>str; if(ch==‘E‘) { if(!m2[str])m2[str]=id++; d=m2[str]; mark[d]=1; s[d].a=str; s[d].b="???"; } else if(ch==‘L‘) { d=m2[str]; mark[d]=0; } else if(ch==‘M‘) { d=m1[str]; for(int i=1; i<=n; i++)if(!mark[i])edg[d][i]=1; //建立反向边 } } } int ans=MaxMatch(); int linkt[N]; for(int i=1; i<=n; i++) //原最大匹配中的边 linkt[i]=link[i]; for(int i=1; i<=n; i++) { d=linkt[i]; edg[d][i]=1; if(MaxMatch()!=ans)s[i].b=s1[d]; //最大匹配减少 edg[d][i]=0; } sort(s+1,s+1+n,cmp); for(int i=1; i<=n; i++) cout<<s[i].a<<":"<<s[i].b<<endl; } return 0; }
POJ 1043 What's In A Name?(唯一的最大匹配方法)
标签:
原文地址:http://www.cnblogs.com/jianrenfang/p/5935520.html