刚刚读这一题时以为这一题与Fire Net一样,后来才发现题目上面阴影部分不影响车的相互攻击,这就说明一行一列只能最多放置一个车。这一题目求放置最多车数目比较好求,直接就是二分匹配最大点集,关键是求重要点个数,那么我们可以依次去掉关联边,再求增广链,看求得的结果与开始求得的结果是否相同,如果不相同,则说明存在一个关键点。
删边的代码:
1 for(int i=1;i<=K;i++) 2 { 3 map[e[i][0]][e[i][1]]=0; 4 int xx=getR(); 5 map[e[i][0]][e[i][1]]=1; 6 if(xx!=ans) 7 Count++; 8 }
所有代码如下:
View Code
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<vector> 5 using namespace std; 6 #define MAXN 105 7 int match[MAXN]; 8 int map[MAXN][MAXN]; 9 int vis [MAXN]; 10 int e[MAXN*MAXN][2]; 11 int N,M,K; 12 13 int find(int x) 14 { 15 for(int i=1;i<=N;i++) 16 { 17 if(map[x][i]&&!vis[i]) 18 { 19 vis[i] = 1; 20 if(!match[i] || find(match[i])) 21 { 22 match[i]= x; 23 return 1; 24 } 25 } 26 } 27 return 0; 28 } 29 int getR() 30 { 31 int ans=0; 32 memset(match,0,sizeof(match)); 33 for(int i=1;i<=N;i++) 34 { 35 memset(vis,0,sizeof(vis)); 36 ans+=find(i); 37 } 38 return ans; 39 } 40 41 int main() 42 { 43 int k=0; 44 while(scanf("%d%d%d",&N,&M,&K)!=EOF) 45 { 46 int a,b; 47 memset(match,0,sizeof(match)); 48 memset(map,0,sizeof(map)); 49 for(int i=1;i<=K;i++) 50 { 51 scanf("%d%d",&a,&b); 52 map[a][b]=1; 53 e[i][0]=a,e[i][1]=b; 54 } 55 int ans=getR(); 56 57 int Count=0; 58 for(int i=1;i<=K;i++) 59 { 60 map[e[i][0]][e[i][1]]=0; 61 int xx=getR(); 62 map[e[i][0]][e[i][1]]=1; 63 if(xx!=ans) 64 Count++; 65 } 66 67 printf("Board %d have %d important blanks for %d chessmen.\n",++k,Count,ans); 68 69 } 70 return 0; 71 }