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 ",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 ",cost); 94 print(0,0); 95 } 96 }