bzoj2150: 部落战争(匈牙利)

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 }

 

posted @ 2018-03-26 09:25  CHerish_OI  阅读(235)  评论(0编辑  收藏  举报