题意:给R*C的房间,每个房间被左上-右下或右上-左下的墙分割为两个小房间,将分割移除有一定花费,问使所有小房间联通需要的最小花费
把每个房间分成左右(上下?)两个点,判一判,本来就联通的加零边,一个房间里的两个点间加花费的边,跑Kruskal即可
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 5 using namespace std; 6 const int maxN=110; 7 8 typedef struct{ 9 int a,b,l; 10 }Edge; 11 12 13 Edge eg[maxN*maxN]; 14 bool stage[maxN][maxN]; //true->\ false->/ 15 int bcj[maxN*maxN*2]; //(i-1)*C+j 16 int T,R,C; 17 18 bool cmp(Edge a,Edge b){ 19 return a.l<b.l; 20 } 21 22 int getf(int i){ 23 return bcj[i]==i?i:bcj[i]=getf(bcj[i]); 24 } 25 26 void add(int a,int b){ //a->b 27 bcj[getf(a)]=getf(b); 28 } 29 30 int main(){ 31 int t,i,j,k,ind,a,b,num,ans; 32 char cr; 33 34 scanf("%d",&T); 35 for(t=1;t<=T;t++){ 36 scanf("%d%d\n",&R,&C); 37 for(i=1;i<=R;i++){ 38 for(j=1;j<=C;j++){ 39 scanf("%c",&cr); 40 stage[i][j]=(cr==‘\\‘); 41 } 42 if(i<R) scanf("\n"); 43 } 44 ind=0; 45 for(i=1;i<=R;i++){ 46 for(j=1;j<=C;j++){ 47 eg[ind].a=(i-1)*C*2+j*2-1; 48 eg[ind].b=(i-1)*C*2+j*2; 49 scanf("%d",&eg[ind++].l); 50 } 51 } 52 for(i=1;i<=R;i++){ 53 ind=(i-1)*C*2; 54 bcj[ind+1]=ind+1; 55 bcj[ind+C*2]=ind+C*2; 56 for(j=1;j<C;j++){ 57 bcj[ind+j*2]=ind+j*2; 58 bcj[ind+j*2+1]=ind+j*2; 59 } 60 } 61 for(i=1;i<R;i++){ 62 for(j=1;j<=C;j++){ 63 ind=(i-1)*C*2+j*2; 64 a=stage[i][j]?ind-1:ind; 65 b=stage[i+1][j]?ind+C*2:ind+C*2-1; 66 add(a,b); 67 } 68 } 69 sort(eg,eg+R*C,cmp); 70 71 ans=0; 72 for(i=0;i<R*C;i++){ 73 if(getf(eg[i].a)!=getf(eg[i].b)){ 74 add(eg[i].a,eg[i].b); 75 ans+=eg[i].l; 76 } 77 } 78 printf("Case %d: %d\n",t,ans); 79 80 } 81 }
原文地址:https://www.cnblogs.com/Ressed/p/9354109.html
时间: 2024-11-05 19:40:54