Problem A: 兔子
Description
兔子不吃窝边草,但是如果一窝兔子吃了另一窝的窝边草怎么办呢?当然是强行挪窝了。
给你兔子窝的数量和位置,求最少要给几窝兔子挪窝。
假设兔子窝的位置为(x,y),则兔子吃草的位置为(x±1,y±1)。
Input
对于每个测试用例,第一行输入两个整数m,n;0<=x<=m,0<=y<=m;n表示有n个兔子窝,m<32;之后n行每行输入两个数,表示兔子窝的位置x,y.
Output
输出一个数,表示需要删掉的兔子窝的数量。
Sample Input
1 1 1 1
Sample Output
0
HINT
范围应该是四个方向, (x+1,y+1),(x+1,y-1),(x-1,y+1),(x-1,y-1)位置不能有其他的兔子窝.
题解:二分图匹配,定义一组匹配 i和 j ,满足二分图的性质(bfs染色不会重)。
#include <bits/stdc++.h> using namespace std; const int MAXN=1005; int uN, vN; int g[MAXN][MAXN]; int linker[MAXN], used[MAXN]; int dfs(int u) { for(int v=1; v<=vN; v++) if(g[u][v] && !used[v]) { used[v]=true; if(linker[v]==-1 || dfs(linker[v])){ linker[v]=u; return true; } } return false; } int hungary() { int res=0; memset(linker, -1, sizeof(linker)); for(int u=1; u<=uN; u++) { memset(used, 0, sizeof(used)); if(dfs(u)) res++; } return res; } int m, n; int x[MAXN], y[MAXN]; int main() { while(~scanf("%d%d", &m, &n)) { memset(g, 0, sizeof(g)); uN=vN=n; for(int i=1; i<=n; i++) scanf("%d%d", &x[i], &y[i]); for(int i=1; i<=n; i++) for(int j=1; j<=n; j++) { if(g[i][j]) continue; if(x[j]==x[i]+1 && y[j]==y[i]+1) g[i][j]=g[j][i]=1; else if(x[j]==x[i]+1 && y[j]==y[i]-1) g[i][j]=g[j][i]=1; else if(x[j]==x[i]-1 && y[j]==y[i]-1) g[i][j]=g[j][i]=1; else if(x[j]==x[i]-1 && y[j]==y[i]+1) g[i][j]=g[j][i]=1; } int ans=hungary()/2; printf("%d\n", ans); } } /************************************************************** Problem: 1189 Language: C++ Result: Accepted Time:21 ms Memory:5984 kb ****************************************************************/