题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=1281
题目概述:
中文题……简单说明下重要点是指这个点必须放一个車的点。
大致思路:
二分图匹配的题目,将每一行1-n作为S集合,每一列1-m作为T集合,如果有一个点(x,y)就将S集合中的x与T集合中的y连一条边代表这个方格。
求重要点就每次删除二分图中的一条边,看最大匹配有没有发生变化,有即为重要点。
代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cmath> 5 #include <vector> 6 #include <ctime> 7 #include <map> 8 #include <queue> 9 #include <cstring> 10 #include <algorithm> 11 using namespace std; 12 13 #define sacnf scanf 14 #define scnaf scanf 15 #define maxn 310 16 #define maxm 26 17 #define inf 1061109567 18 #define Eps 0.00001 19 const double PI=acos(-1.0); 20 #define mod 7 21 #define MAXNUM 10000 22 void Swap(int &a,int &b) {int t=a;a=b;b=t;} 23 double Abs(double x) {return (x<0)?-x:x;} 24 typedef long long ll; 25 typedef unsigned int uint; 26 27 int n,m,k; 28 int x[maxn],y[maxn]; 29 int G[maxn][maxn]; 30 int vis[maxn],l[maxn]; 31 32 bool dfs(int u) 33 { 34 for(int i=1;i<=n+m;i++) 35 { 36 if(!G[u][i]) continue; 37 if(!vis[i]) 38 { 39 vis[i]=1; 40 if(l[i]==-1||dfs(l[i])) 41 { 42 l[i]=u;return true; 43 } 44 } 45 } 46 return false; 47 } 48 49 int hungary() 50 { 51 int cnt=0; 52 memset(l,-1,sizeof(l)); 53 for(int i=1;i<=n;i++) 54 { 55 memset(vis,0,sizeof(vis)); 56 if(dfs(i)) cnt++; 57 } 58 return cnt; 59 } 60 61 int main() 62 { 63 //freopen("data.in","r",stdin); 64 //freopen("data.out","w",stdout); 65 //clock_t st=clock(); 66 int kase=0; 67 while(~scnaf("%d%d%d",&n,&m,&k)) 68 { 69 kase++; 70 for(int i=1;i<=n;i++) 71 { 72 for(int j=1;j<=n+m;j++) G[i][j]=0; 73 } 74 for(int i=1;i<=k;i++) 75 { 76 scanf("%d%d",&x[i],&y[i]); 77 G[x[i]][n+y[i]]=G[n+y[i]][x[i]]=1; 78 } 79 int ans1=hungary(),ans2=0; 80 for(int i=1;i<=k;i++) 81 { 82 G[x[i]][n+y[i]]=G[n+y[i]][x[i]]=0; 83 if(hungary()!=ans1) ans2++; 84 G[x[i]][n+y[i]]=G[n+y[i]][x[i]]=1; 85 } 86 printf("Board %d have %d important blanks for %d chessmen. ",kase,ans2,ans1); 87 } 88 //clock_t ed=clock(); 89 //printf(" Time Used : %.5lf Ms. ",(double)(ed-st)/CLOCKS_PER_SEC); 90 return 0; 91 }