Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 2083 | Accepted: 741 |
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
题目大意:
坏人有网名和真名,知道他们真名离开和进入房间的时间
也知道他们网名的发言时间,求网名和真名的匹配
实际上就是二分图匹配,首先默认所有点都是相连的,再通过他们的进出时间排除所有不可能的情况,再匈牙利算法匹配
#include <iostream> #include <cstdio> #include <cstring> #include <string> #include <algorithm> #include <vector> #include <cmath> using namespace std; int n ; int sum = 0; //进去的人的数目 int is_in[25] ; char name[25][25], id[25][25]; int g[25][25]; //前一项表示人名,后一项表示网名 int inde[25]; //表示人名i能与网名inde[i]匹配,如不能,则为-1 int r[25]; //排序时用的序数 const int MAXN = 25; int uN,vN; int linker[MAXN]; bool used[MAXN]; bool dfs(int u){ int v; for(v=0;v<vN;v++) if(g[u][v]&&!used[v]){ used[v]=true; if(linker[v]==-1||dfs(linker[v])){ linker[v]=u; return true; } } return false; } int hungary(){ int res=0; int u; memset(linker,-1,sizeof(linker)); for(u=0;u<uN;u++){ memset(used,0,sizeof(used)); if(dfs(u)) res++; } //cout << "res=" << res << endl; return res; } void solve(){ int i, j, k; for(i = 0; i < n; i ++){ for(j = 0; j < n; j ++){ if(g[i][j]){ g[i][j] = 0; if(hungary() < n){ g[i][j] = 1; break; } g[i][j] = 1; } } //cout << "j=" << j << endl; if(j == n){ inde[i] = -1; } else{ inde[i] = j; } } } inline int cmp(int i,int j){ if (memcmp(name[i],name[j],sizeof name[i]) <= 0) return 1; else return 0; } int main(){ int i, j, k; scanf("%d", &n); uN = n; vN = n; int sum = 0;//房间里人数量 memset(g, 1, sizeof(g)); for(i = 0; i < n; i ++){ scanf("%s", id[i]); } scanf("\n"); char tmp; char stmp[25]; for (scanf("%c",&tmp); tmp != 'Q'; scanf("%c",&tmp)){ scanf("%s\n", stmp); switch(tmp){ case 'E': for(i = 0; i < sum; i ++){ if(strcmp(stmp, name[i]) == 0) break; } if(i == sum) strcpy(name[sum ++], stmp); is_in[i] = 1; break; case 'L': for(i = 0; i < sum; i ++){ if(strcmp(stmp, name[i]) == 0) break; } is_in[i] = 0; break ; case 'M': for(i = 0; i < n; i ++){ if(strcmp(stmp, id[i]) == 0) break; } for(j = 0; j < n; j ++){ if(!is_in[j]) g[j][i] = 0; //排除所有不可能情况,注意i,j不要写反 } break ; } } solve(); for(i = 0; i < n; i ++){ r[i] = i; } sort(r, r + n, cmp); for(i = 0; i < n; i ++){ printf("%s:", name[r[i]]); if(inde[r[i]] == -1) printf("???\n" ) ; else printf("%s\n", id[inde[r[i]]]); } return 0; }