这题也是简单的模板应用,但是有一点不一样;
重要点:如果取消这个点,不能放置尽量多的棋子,比如原来可以放3个,如果不放这个只能放2个,说明它是一个重要点;
这题的解题思路就是:先算出最大匹配数,然后把读入的可放置点的坐标依次取消标记,再算一次最大匹配,如果两次匹配结果相等,说明其不是重要点,记录数加1,算完要记得还原标记;
最后计算出来的时候记得用最大棋子数减掉记录数;
下面附上代码:
1 #include <iostream> 2 #include <string.h> 3 using namespace std; 4 #define MAXN 105 5 int uN,vN;//u,v数目 6 int map[MAXN][MAXN]; 7 int linker[MAXN]; 8 bool used[MAXN]; 9 int x[MAXN],y[MAXN]; 10 bool dfs(int u)//从左边开始找增广路径 11 { 12 int v; 13 for(v=1;v<=vN;v++)//这个顶点编号从0开始,若要从1开始需要修改 14 if(map[u][v]&&!used[v]) 15 { 16 used[v]=true; 17 if(linker[v]==-1||dfs(linker[v])) 18 {//找增广路,反向 19 linker[v]=u; 20 return true; 21 } 22 } 23 return false;//这个不要忘了,经常忘记这句 24 } 25 int hungary() 26 { 27 int res=0; 28 int u; 29 memset(linker,-1,sizeof(linker)); 30 for(u=1;u<=uN;u++) 31 { 32 memset(used,0,sizeof(used)); 33 if(dfs(u)) res++; 34 } 35 return res; 36 } 37 int main() 38 { 39 int k,a,b,count,ans,res; 40 int t = 1; 41 //freopen("1281.txt","r",stdin); 42 while(~scanf("%d %d %d",&uN,&vN,&k)) 43 { 44 count = 0; 45 memset(map,0,sizeof(map)); 46 for(int i = 0; i < k ; i++) 47 { 48 scanf("%d %d",&a,&b); 49 map[a][b] = 1; 50 x[i] = a;y[i] =b; 51 } 52 int ans = hungary(); 53 for(int i = 0 ;i < k ; i++) 54 { 55 map[x[i]][y[i]] = 0; 56 res = hungary(); 57 if(res == ans) 58 count ++; 59 map[x[i]][y[i]] = 1; 60 } 61 printf("Board %d have %d important blanks for %d chessmen.\n",t++,k-count,ans); 62 63 } 64 return 0; 65 }
原文:http://www.cnblogs.com/xiaoniuniu/p/4395727.html