Dungeons and Candies

Zepto Code Rush 2014:http://codeforces.com/problemset/problem/436/C

题意:k个点,每个点都是一个n * m的char型矩阵。对与每个点,权值为n * m或者找到一个之前的点,取两个矩阵对应位置不同的字符个数乘以w。找到一个序列,使得所有点的权值和最小。

题解:很明显的最小生成树。但是要加入一个0点,边权为n*m,其余k个点两两建立一条边,边权是diff[i][j]*w,最后这一题,我要死掉的地方就是输出,不仅要输出费用,还要输出边,但是这里的边,看了半天,才知道,要按dfs序列输出,并且第一个点的前一个点必须是0.哎,这一题,只能说明自己太渣了。有点伤心。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 using namespace std;
 6 int n,m,k,w,num,cost,ct;
 7 int fa[1002];
 8 int g[1002][1002];
 9 void init(){
10    for(int i=0;i<=k;i++)
11       fa[i]=i;
12 }
13 int  Find(int x){
14     int s;
15     for(s=x;s!=fa[s];s=fa[s]);
16     while(s!=x){
17         int temp=fa[x];
18         fa[x]=s;
19         x=temp;
20     }
21    return s;
22 }
23 struct Node{
24   int x;
25   int y;
26   int val;
27 }edge[1000002];
28 int cmp1(Node a,Node b){
29   return a.val<b.val;
30 }
31 int cmp2(Node a,Node b){
32    return a.y<b.y;
33 }
34 char mp[1002][12][12];
35 void deal(){
36    for(int i=1;i<=k;i++){
37       for(int j=i+1;j<=k;j++){
38         int counts=0;
39         for(int g=1;g<=n;g++){
40             for(int h=1;h<=m;h++){
41                 if(mp[i][g][h]!=mp[j][g][h])
42                     counts++;
43             }
44         }
45         edge[++num].x=i;
46         edge[num].y=j;
47         edge[num].val=counts*w;
48       }
49    }
50    for(int i=1;i<=k;i++){
51      edge[++num].x=0;
52      edge[num].y=i;
53      edge[num].val=n*m;
54    }
55 }
56 void print(int u,int fa){
57      for(int i=0;i<=k;i++){
58         if(g[u][i]>=0&&i!=fa){
59             printf("%d %d\n",i,u);
60              print(i,u);
61         }
62      }
63 
64 
65 }
66 int main(){
67     while(~scanf("%d%d%d%d",&n,&m,&k,&w)){
68         init();
69         memset(g,-1,sizeof(g));
70         for(int i=1;i<=k;i++){
71             for(int j=1;j<=n;j++){
72                 for(int h=1;h<=m;h++)
73                     cin>>mp[i][j][h];
74             }
75         }
76         num=0;
77         deal();
78         sort(edge+1,edge+num+1,cmp1);
79         ct=0;cost=0;
80         for(int i=1;i<=num;i++){
81             int x=Find(edge[i].x);
82             int y=Find(edge[i].y);
83             if(x!=y){
84                 fa[x]=y;
85                 int tx=edge[i].y;
86                 int ty=edge[i].x;
87                  g[tx][ty]=g[ty][tx]=edge[i].val;
88                  ct++;
89                    cost+=edge[i].val;
90             }
91             if(ct==k)break;
92         }
93            printf("%d\n",cost);
94                 print(0,0);
95     }
96 }
View Code

 

posted on 2014-07-29 20:25  天依蓝  阅读(249)  评论(0编辑  收藏  举报

导航