原题连接:点击打开链接
题意:…………
思路:求最多能放多少个 “车”,可以转化成 二分图的最大匹配!,把能放的点的 横纵坐标 当作 二分图的一条边!最大匹配就满足了题目中任意两个“车”不会互相吃到的条件,因为匹配结果,会使得棋盘中的匹配点(也就是二分图中的匹配边),不在同一列且不再同一行。求出最大匹配后 ,则重要点必定在最大匹配的边上!依次去掉每条便,再求最大匹配看和原匹配是否相等即可!
代码:
#include<cstdio> #include<cstring> #include<queue> #include<vector> #include<iostream> #include<algorithm> using namespace std; vector<int>V[1000]; int link[1000],use[1000]; void init(int n) { int i; for(i=0;i<=n;i++) V[i].clear(); } bool Dfs(int v) { int i,j,k; for(i=0;i<V[v].size();i++) { k=V[v][i]; if(!use[k]) { use[k]=1; if(!link[k]||Dfs(link[k])) { link[k]=v; return true; } } } return false; } int MaxMatch(int n) { int i,j,ans=0; memset(link,0,sizeof(link)); for(i=1;i<=n;i++) { memset(use,0,sizeof(use)); if(Dfs(i)) ans++; } return ans; } int main() { int i,j,n,m,k,t=0; while(~scanf("%d%d%d",&n,&m,&k)) { t++; init(n); int x,y; while(k--) { scanf("%d%d",&x,&y); V[x].push_back(y); } int ans=MaxMatch(n); int imp=0; for(i=1;i<=n;i++) { for(j=0;j<V[i].size();j++) { k=V[i][j]; V[i].erase(V[i].begin()+j); // printf("去掉边 %d----%d\n",i,k); int cnt=MaxMatch(n); if(cnt<ans) imp++; V[i].insert(V[i].begin()+j,k); } } printf("Board %d have %d important blanks for %d chessmen.\n",t,imp,ans); } }