blue sea  
As an ACMer, not only try, but also create.

题意:

有n(1<=n<=20)个人,每一个人在发电报的时候是以固定的绰号发送的,现在给定一串序列表示某个人进入房间,某个人从房间出去,或者截获了以什么绰号发送的电报,问能否推出每个人对应的绰号是什么,如果推理不出来输出"???"。

解题思路:

如果删除某边后最大匹配数变小,这条边便是唯一匹配方案,是所要的答案

View Code
  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,感觉功能好犀利。

posted on 2012-12-02 11:43  wide sea  阅读(251)  评论(0)    收藏  举报