【treedp】2010final F.Keys

https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=547&page=show_problem&problem=4042k

    真的不明白自己为什么会老犯a打成b之类的sb错误=。=~~。打错字母再次卡了一个多钟!!!

    给你一系列钥匙跟钥匙环,钥匙系在钥匙环上,钥匙环可以系在一起组成一个森林结构。。每次操作有2种分别是把钥匙从环上解下或系上,另外一种是把环与环解开或系上。。。要求最少的操作次数将A-M的钥匙弄在同一棵由环组成的树上,同时N-Z的钥匙需要再另外一棵树上。。这里最少操作数是指保证第一种操作最少的同时第二种最少。

   做法很简单,每个环分别统计其上两种钥匙的数量,将其分成3种环,或者是属于A-M钥匙的0类环,或者是属于N-Z的1类环,或者都可以的2类环。。再进行一个简单dp即可。。这里要主要一下dp前要保证至少有1个0类环以及至少有1个1类环,如不满足可以通过枚举来强制转换环的类型。另外再把其中一类钥匙没出现的情况,还有无解情况特判掉。。

View Code
  1 //By Lin
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<algorithm>
  6 #include<set>
  7 #include<vector>
  8 #include<map>
  9 #include<queue>
 10 
 11 #define sqr(x) ((x)*(x))
 12 #define Rep(i,n) for(int i = 0; i<n; i++)
 13 #define foreach(i,n) for( __typeof(n.begin()) i = n.begin(); i!=n.end(); i++)
 14 #define X first
 15 #define Y second
 16 #define mp(x,y) make_pair(x,y)
 17 
 18 using namespace std;
 19 typedef long long LL;
 20 typedef pair<int,int> pii;
 21 #define N 30
 22 #define inf 0x7fffffff
 23 int        ecnt;
 24 struct    Edge{
 25     int to;
 26     Edge *next;
 27 }*mat[N],edges[N*2];
 28 void    link(int x,int to){
 29     edges[ecnt].to = to;
 30     edges[ecnt].next = mat[x];
 31     mat[x] = &edges[ecnt++];
 32 }
 33 
 34 int        dp[30][2][2];
 35 int        kind[30];
 36 int        num[30][2],n,mm[N],tol[2];
 37 char    str[N];
 38 bool    mark[N];
 39 
 40 void    check(int &x,int y){
 41     if ( x == -1 || x > y ) x = y;
 42 }
 43 int        id(char ch){
 44     int k = ch-'a';
 45     if ( mm[k] == -1 ) mm[k] = n++;
 46     return mm[k];
 47 }
 48 bool    dfs(int x,int father){
 49     mark[x] = true;
 50     memset( dp[x] , 0 , sizeof(dp[x]) );
 51     bool    ret = num[x][0]+num[x][1]>0;
 52     for ( Edge *p = mat[x]; p ; p = p->next ){
 53         int to = p->to;
 54         if ( to == father ) continue;
 55         ret |= dfs(to,x);
 56         Rep(i,2) Rep(j,2){
 57             if ( kind[x]<2 && kind[x]!=i ) continue;
 58             if ( (num[x][0]+num[x][1]>0  || kind[x]<2 )&& j == 0 ) continue;
 59             int    tmp = inf;
 60             Rep(g,2) Rep(h,2){
 61                 if ( kind[to]<2 && kind[to]!=g ) continue;
 62                 if ( (num[to][0]+num[to][1]>0 || kind[to]<2 ) && h == 0 ) continue;
 63                 int K = 0;
 64                 if ( h == 1 && j == 0 ) K = 2;
 65                 else if ( i != g ) K = 1+(h?1:0);
 66                 tmp = min( tmp , dp[to][g][h]+K );
 67             }
 68             dp[x][i][j] += tmp;
 69         }
 70     }
 71 //    printf("%d kind %d\n" , x , kind[x] );
 72 //    Rep(i,2) Rep(j,2){
 73 //        if ( kind[x]<2 && kind[x]!=i ) continue;
 74 //        if ( (num[x][0]+num[x][1]>0 || kind[x]<2 )&& j == 0 ) continue;
 75 //        printf("dp[%d][%d][%d]= %d\n", x, i , j , dp[x][i][j] );
 76 //    }
 77     return ret;
 78 }
 79 
 80 int        solve(){
 81     int    ret = 0;
 82     memset( mark , false , sizeof(mark) );
 83     Rep(i,n){
 84         if ( mark[i] ) continue;
 85         dfs(i,-1);
 86         int    tmp = inf;
 87         Rep(g,2) Rep(h,2){
 88             if ( kind[i]<2 && kind[i]!=g ) continue;
 89             if ( (num[i][0]+num[i][1]>0 || kind[i]<2 ) && h == 0 ) continue;
 90 //            printf("%d %d val %d\n" , g , h , dp[i][g][h] );
 91             tmp = min( tmp , dp[i][g][h]+(h?1:0) );
 92         }
 93         ret += tmp;
 94     }
 95     return ret-2;
 96 }
 97 
 98 int        main(){
 99     int    tt = 0;
100     while ( ~scanf("%s", str ) ){
101         memset( num , 0 , sizeof(num) );
102         ecnt = 0;
103         memset( mat , 0 , sizeof(mat) );
104         n = 0;
105         memset( mm , -1 , sizeof(mm) );
106         tol[0] = tol[1] = 0;
107 
108         do{
109             int    g,h;
110             if ( islower(str[0] ) ) g = id(str[0]);
111             else g = str[0]<='M'?-1:-2;
112             if ( islower(str[1] ) ) h = id(str[1]);
113             else h = str[1]<='M'?-1:-2;
114             if ( g >= 0 && h >= 0 ) link(g,h),link(h,g);
115             else if ( h < 0 ) num[g][h+2]++;
116             else if ( g < 0 ) num[h][g+2]++;
117             scanf("%s", str );
118         } while ( str[0] != '0' );
119         printf("Case %d: ", ++tt );
120 
121         if ( n == 1 && num[0][0]>0 && num[0][1]>0 ) {
122             printf("impossible\n");
123             continue;
124         }
125         Rep(i,n) tol[0] += num[i][0], tol[1] += num[i][1];
126         bool    ha = false , hb = false;
127         int        a = 0,b;
128         Rep(i,n){
129             if ( num[i][0]> num[i][1] ) { kind[i] = 0; ha = true; }
130             if ( num[i][0]< num[i][1] ) { kind[i] = 1; hb = true; }
131             if ( num[i][0]==num[i][1] ) kind[i] = 2;
132             a += min(num[i][0],num[i][1]);
133         }
134         if ( tol[0] == 0 && tol[1] == 0 ) b = 0; 
135         else if ( tol[0] == 0 || tol[1] == 0 ){
136             b = 0;
137             memset(mark,false,sizeof(mark));
138             Rep(i,n) if ( !mark[i] ) {
139                 if ( dfs(i,-1) ) b ++;
140             }
141             b--;
142         }
143         else{
144             int    da = inf, db = inf;
145             Rep(i,n) da = min( da , num[i][1]-num[i][0] );
146             Rep(i,n) db = min( db , num[i][0]-num[i][1] );
147             if ( !ha && !hb ){
148                 b = inf;
149                 Rep(i,n) if ( num[i][1]-num[i][0]==da ){
150                     Rep(j,n) if ( num[j][0]-num[j][1]==db ){
151                         if ( i == j ) continue;
152                         int    p = kind[i], q = kind[j];
153                         kind[i] = 0;
154                         kind[j] = 1;
155                         b = min(b,solve());
156                         kind[i] = p; 
157                         kind[j] = q;
158                     }
159                 }
160             }
161             else if ( !ha ){
162                 a += da; 
163                 b = inf;
164                 Rep(i,n) if ( num[i][1]-num[i][0]==da ){
165                     int    p = kind[i];
166                     kind[i] = 0;
167                     b = min(b,solve());
168                     kind[i] = p;
169                 }
170             }
171             else if ( !hb ){
172                 a += db; 
173                 b = inf;
174                 Rep(i,n) if ( num[i][0]-num[i][1]==db ){
175                     int    p = kind[i];
176                     kind[i] = 1;
177                     b = min(b,solve());
178                     kind[i] = p;
179                 }
180             }
181             else b = solve();
182         }
183         a *= 2;
184         printf("%d %d\n" , a , b );
185     }
186     return 0;
187 }

 

posted @ 2013-03-15 14:50  lzqxh  阅读(203)  评论(0编辑  收藏  举报