1. 程式人生 > >bzoj2150: 部落戰爭

bzoj2150: 部落戰爭

nod gpo ring main fin AR post class printf

補了一下匈牙利的各種騷操作。

最大匹配等於最小覆蓋

最大獨立集=n-最小覆蓋

最大團=補圖的最大獨立集

對於這題,把每個點拆成兩個,可以到達的就連邊。

我匈牙利的模版是真不熟。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
int dx[4]={1,1,1,1};
int dy[4
]={1,-1,1,-1}; struct node { int x,y,next; }a[210000];int len,last[3100]; void ins(int x,int y) { len++; a[len].x=x;a[len].y=y; a[len].next=last[x];last[x]=len; } int match[3100]; bool chw[3100]; bool find_muniu(int x) { for(int k=last[x];k;k=a[k].next) { int
y=a[k].y; if(chw[y]==true) { chw[y]=false; if(match[y]==0||find_muniu(match[y])==true) { match[y]=x; return true; } } } return false; } int nm,num[110][110]; char ss[110][110];
int main() { int n,m,R,C; scanf("%d%d%d%d",&n,&m,&R,&C); for(int i=0;i<=1;i++) { dx[i]*=R,dy[i]*=C; dx[i+2]*=C,dy[i+2]*=R; } nm=0; for(int i=1;i<=n;i++) { scanf("%s",ss[i]+1); for(int j=1;j<=m;j++) if(ss[i][j]==.)num[i][j]=++nm; } for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(ss[i][j]==.) for(int t=0;t<=3;t++) { int ti=i+dx[t],tj=j+dy[t]; if(ti>0&&ti<=n&&tj>0&&tj<=m&&ss[ti][tj]==.) ins(num[i][j],num[ti][tj]); } int ans=0; memset(match,0,sizeof(match)); for(int i=1;i<=nm;i++) { memset(chw,true,sizeof(chw)); if(find_muniu(i)==true)ans++; } printf("%d\n",nm-ans); return 0; }

bzoj2150: 部落戰爭