题意:
有n(1<=n<=20)个人,每一个人在发电报的时候是以固定的绰号发送的,现在给定一串序列表示某个人进入房间,某个人从房间出去,或者截获了以什么绰号发送的电报,问能否推出每个人对应的绰号是什么,如果推理不出来输出"???"。
解题思路:
如果删除某边后最大匹配数变小,这条边便是唯一匹配方案,是所要的答案

1 #include<cstdio> // poj 1043 What's In A Name? 2 #include<iostream> // 224K 47MS C++ 3 #include<cstring> 4 #include<string> 5 #include<algorithm> 6 #include<map> // 该题字符串的处理很多,用了 map 和 set 来存储数据 7 #include<set> 8 using namespace std; 9 10 const int MAXN = 30; 11 int T, cas; 12 int n; 13 string real[MAXN], reco[MAXN]; // 用户名和代号 14 string sign, name; // 输入所用的变量 15 map< string, int >mp1; // 用来保存用户名 16 map< string, int >mp2; // 用来记录代号 17 bool g[MAXN][MAXN], vis[MAXN]; // 17-18 匈牙利算法所用的变量 18 int cx[MAXN], cy[MAXN], nx, ny; 19 set< int >cur; // set 的插入与消去,好好用,第一次实用 20 pair< string, int >pair1[MAXN]; // 20-21 解的保存,pair的第一次实用 21 int os[MAXN]; 22 /**************** 1-3 函数是算法模板 **********************/ 23 void init() 24 { 25 memset( g, true, sizeof(g) ); 26 } 27 28 int dfs( int u ) 29 { 30 int v; 31 for( v = 1; v <= ny; v++ ) 32 { 33 if( g[u][v] && !vis[v] ) 34 { 35 vis[v] = true; 36 if( !cy[v] || dfs( cy[v] ) ) 37 { 38 cx[u] = v; 39 cy[v] = u; 40 return 1; 41 } 42 } 43 } 44 return 0; 45 } 46 47 int MaxMatch() 48 { 49 int u, ret; 50 memset( cx, 0, sizeof(cx) ); 51 memset( cy, 0, sizeof(cy) ); 52 ret = 0; 53 for( u = 1; u <= nx; u++ ) 54 { 55 if( !cx[u] ) 56 { 57 memset( vis, false, sizeof(vis) ); 58 ret += dfs( u ); 59 } 60 } 61 return ret; 62 } 63 /************ 数据的读入 ***************/ 64 void readcase() 65 { 66 int i; 67 scanf( "%d", &n ); 68 for( i = 1; i <= n; i++ ) 69 { 70 cin>>real[i]; 71 mp1[real[i]] = i; 72 } 73 int cnt; 74 cnt = 0; 75 while( cin>>sign, sign != "Q" ) 76 { 77 cin>>name; 78 if( sign == "E" ) 79 { 80 if( mp2[name] == 0 ) 81 { 82 mp2[name] = ++cnt; 83 reco[cnt] = name; 84 } 85 int y = mp2[name]; 86 cur.insert( y ); // set 的插入 87 } 88 else if( sign == "L" ) 89 { 90 int y = mp2[name]; 91 cur.erase( y ); // set 的消去元素 92 } 93 else 94 { 95 int x = mp1[name]; 96 for( i = 1; i <= n; i++ )if( cur.find( i ) == cur.end() ) 97 g[x][i] = false; // 去掉没有关系的边 98 } 99 } 100 nx = ny = n; // 待验证?????????????????????? 101 } 102 103 void deal( int mat ) // 枚举去掉存在的边,在求最大匹配,如减少,则该边存在 104 { 105 int i, j, tmp; 106 for( i = 1; i <= n; i++ ) 107 { 108 pair1[i] = make_pair( reco[i], i ); 109 os[i] = 0; 110 for( j = 1; j <= n; j++ ) 111 { 112 if( g[j][i] ) 113 { 114 g[j][i] = false; 115 tmp = MaxMatch(); 116 if( tmp != mat ) 117 { 118 os[i] = j; 119 } 120 g[j][i] = true; 121 } 122 } 123 } 124 sort( pair1 + 1, pair1 + n +1 ); // 对解的排序 125 } 126 127 void print() 128 { 129 int i, j; 130 for( i = 1; i <= n; i++ ) 131 { 132 cout<< pair1[i].first << ":"; 133 if( os[pair1[i].second] == 0 ) 134 cout<< "???" << endl; 135 else 136 cout<< real[os[pair1[i].second]] << endl; 137 } 138 } 139 int main() 140 { 141 init(); 142 readcase(); 143 int mat; 144 mat = MaxMatch(); 145 deal( mat ); 146 print(); 147 return 0; 148 }
这个是八数码问题??
不清楚吧,当二分图来练习了。
用STL来A题,这是头一次,map,set,感觉功能好犀利。