[HEOI2016]游戏

链接

思路:搞出所有横的和竖的联通块,然后两个联通块交点是*的话就连条边,直接二分图匹配即可。

PS:点数好多啊,空间开炸了,调了0.5H

 1 // It is made by XZZ
 2 #include<cstdio>
 3 #include<algorithm>
 4 using namespace std;
 5 #define rep(a,b,c) for(rg int a=b;a<=c;a++)
 6 #define drep(a,b,c) for(rg int a=b;a>=c;a--)
 7 #define erep(a,b) for(rg int a=fir[b];a;a=nxt[a])
 8 #define il inline
 9 #define rg register
10 #define vd void
11 typedef long long ll;
12 il int gi(){
13     rg int x=0,f=1;rg char ch=getchar();
14     while(ch<'0'||ch>'9')f=ch=='-'?-1:f,ch=getchar();
15     while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
16     return x*f;
17 }
18 const int maxn=1500,S=1498,T=1499,maxm=10000<<1;
19 int fir[maxn],dis[maxm],nxt[maxm],w[maxm],id=1;
20 char chess[55][55];
21 il vd add(int a,int b,int ww){
22     nxt[++id]=fir[a],dis[id]=b,w[id]=ww,fir[a]=id;
23     if(ww)add(b,a,0);
24 }
25 int dep[maxn];
26 il bool BFS(){
27     int que[maxn],hd=0,tl=1;bool vis[maxn]={0};
28     que[0]=S,dep[S]=1,vis[S]=1;
29     while(hd^tl){
30         int now=que[hd++];
31         erep(i,now)
32             if(w[i]>0&&!vis[dis[i]])
33         vis[dis[i]]=1,dep[dis[i]]=dep[now]+1,que[tl++]=dis[i];
34     }
35     return vis[T];
36 }
37 il int Dinic(int now,int rest){
38     if(now==T)return rest;
39     int flow=rest;
40     erep(i,now)
41         if(w[i]>0&&w[i]<=rest&&dep[dis[i]]==dep[now]+1){
42             int Flow=Dinic(dis[i],min(w[i],rest));
43             w[i]-=Flow,w[i^1]+=Flow,rest-=Flow;
44             if(!rest)return flow;
45         }
46     return flow-rest;
47 }
48 int index[55][55][2];
49 int main(){
50     freopen("heoi2016_game.in","r",stdin);
51     freopen("heoi2016_game.out","w",stdout);
52     int n,m,num=0;
53     scanf("%d%d",&n,&m);
54     rep(i,1,n)scanf("%s",chess[i]+1);
55     rep(i,1,n)rep(j,1,m){
56         if(chess[i][j]=='#')continue;
57         if(chess[i][j-1]=='#'||j==1)++num,add(S,num,1);
58         index[i][j][0]=num;
59     }
60     rep(j,1,m)rep(i,1,n){
61         if(chess[i][j]=='#')continue;
62         if(chess[i-1][j]=='#'||i==1)++num,add(num,T,1);
63         index[i][j][1]=num;
64     }
65     rep(i,1,n)rep(j,1,m)
66     if(chess[i][j]=='*')add(index[i][j][0],index[i][j][1],1);
67     int flow=0;
68     while(BFS())flow+=Dinic(S,23333);
69     printf("%d
",flow);
70     return 0;
71 }
Copy His Code
原文地址:https://www.cnblogs.com/xzz_233/p/7150716.html