1. 程式人生 > >bzoj2150: 部落戰爭(匈牙利)

bzoj2150: 部落戰爭(匈牙利)

ace ali IT 最大匹配 AI 最小路徑 namespace ins ||

2150: 部落戰爭

題目:傳送門


題解:

   辣雞數據..毀我AC率

   先說做法,很容易就可以看出是二分圖匹配的最小路徑覆蓋(可能是之前不久剛做過類似的題)

   一開始還傻逼逼的去直接連邊然後準備跑floyd...肯定是做祭祀做傻了

   二分圖嘛,將每個點拆成兩個集合再連啊...

   然後最小路徑覆蓋=總點數-最大匹配數

   強烈吐槽!個人習慣用數組存點編號...50*50的數據範圍我開55*55...結果WA n次

   然後...改成56*56...AC。。。ORZ

  


代碼:

 1 #include<cstdio>
 2
#include<cstring> 3 #include<cstdlib> 4 #include<cmath> 5 #include<algorithm> 6 using namespace std; 7 struct node 8 { 9 int x,y,next; 10 }a[25000];int len,last[25000]; 11 void ins(int x,int y) 12 { 13 len++;a[len].x=x;a[len].y=y; 14 a[len].next=last[x];last[x]=len;
15 } 16 char s[55][55]; 17 int n,m,R,C,t; 18 int match[25000],chw[25000]; 19 bool findmuniu(int x) 20 { 21 for(int k=last[x];k;k=a[k].next) 22 { 23 int y=a[k].y; 24 if(chw[y]!=t) 25 { 26 chw[y]=t; 27 if(match[y]==0 || findmuniu(match[y]))
28 { 29 match[y]=x; 30 return true; 31 } 32 } 33 } 34 return false; 35 } 36 int d[56][56];//辣雞數據 37 int main() 38 { 39 scanf("%d%d%d%d",&n,&m,&R,&C); 40 for(int i=1;i<=n;i++)scanf("%s",s[i]+1); 41 int ss=0;memset(d,-1,sizeof(d)); 42 for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)d[i][j]=++ss; 43 const int dx[5]={0,R,R,C,C}; 44 const int dy[5]={0,-C,C,-R,R}; 45 int sum=0;len=0;memset(last,0,sizeof(last)); 46 for(int i=1;i<=n;i++) 47 for(int j=1;j<=m;j++) 48 if(s[i][j]==.) 49 { 50 sum++; 51 for(int k=1;k<=4;k++) 52 { 53 int x=i+dx[k],y=j+dy[k]; 54 if(d[x][y]!=-1 && s[x][y]!=x) 55 ins(d[i][j],d[x][y]+n*m); 56 } 57 } 58 memset(match,0,sizeof(match)); 59 memset(chw,0,sizeof(chw)); 60 int ans=0; 61 for(int i=1;i<=n;i++) 62 for(int j=1;j<=m;j++) 63 if(s[i][j]==.) 64 { 65 t++; 66 if(findmuniu(d[i][j]))ans++; 67 } 68 printf("%d\n",sum-ans); 69 return 0; 70 }

bzoj2150: 部落戰爭(匈牙利)