hdu 4185
http://acm.hdu.edu.cn/showproblem.php?pid=4185
题意:给一个二维的地图,地图只有'.'和'#',问最多有多少对‘#’,一对‘#’要相邻。
思路:很明显,是一个二分匹配的题目,当时考虑到600*600个点,不敢写,随后弄了个贪心的算法:
把地图转化成一个无向图,并记录第个点的度。优先匹配度为1的点,再次是度为2的点,度为3和4的点是不会先匹配的,
然后就相当于维护两个队列,并标记每个点是否已被访问和度的变化。
这个想法好像没什么 问题,但一直wa。随后想不出有什么好的二分匹配算法,看解题才知道,居然是裸二分图,orz~~~
PS:这套题的数据好像不是很严谨,前面出了的题目程序还有点小bug,但也过了,hdu这个水库~~~
View Code
#include<set> #include<map> #include<stack> #include<queue> #include<cmath> #include<bitset> #include<string> #include<climits> #include<cstdio> #include<vector> #include<utility> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #define IN puts("in") #define OUT puts("out") #define FR(x) freopen(x,"r",stdin) #define FW(x) freopen(x,"w",stdout) #define MSET(x,y) memset(x,y,sizeof(x)) #define ST system("pause") #define lowbit(x) (x)&(-x) #define L(x) (x)<<1 #define R(x) ((x)<<1)^1 using namespace std; const int maxn = 605; char str[maxn][maxn]; int head[maxn*maxn],vis[maxn*maxn],Link[maxn*maxn],st[maxn*maxn]; int n,ecnt,tp; int dx[] = {1,-1,0,0}; int dy[] = {0,0,-1,1}; struct nd{ int u,v,next; }edge[maxn*maxn*5]; bool isok(int x,int y) { if(x==n||y==n||x<0||y<0||str[x][y]!='#')return false; return true; } void add(int u,int v) { edge[ecnt].u = u; edge[ecnt].v = v; edge[ecnt].next = head[u]; head[u] = ecnt++; } bool dfs(int u) { int i,v; for(i = head[u]; i != -1; i = edge[i].next){ v = edge[i].v; if(vis[v])continue; vis[v] = 1; st[++tp] = v; if(Link[v]==0||dfs(Link[v])){ Link[v] = u; return true; } }return false; } int main() { int i,j,k,t,cas=0; scanf("%d",&t); while(t--){ scanf("%d",&n); for(i = 0; i < n; ++ i)scanf("%s",str[i]); memset(head,-1,sizeof(head)); ecnt = 0; for(i = 0; i < n; ++ i) for(j = 0; j < n; ++ j)if(str[i][j]=='#') for(k = 0; k < 4; ++ k) { int x = i + dx[k]; int y = j + dy[k]; if(isok(x,y)) add(i*n+j+1,x*n+y+1); } k = 0; MSET(Link,0); for(i = 1; i <= n * n; ++ i){ MSET(vis,0); if(dfs(i))++k; while(tp)vis[st[tp--]] = 0; } printf("Case %d: %d\n",++cas,k/2); } return 0; }

浙公网安备 33010602011771号