题目连接
N * M 的矩阵上,规定几个方格可以放车(ju),
求最多放几个车互不冲突,哪些车是import(这个点不放(最大放车数会减少))
思路:
1)我们需要求一下最大放车数
2)一行一列只能有一个车 (把行和列看成两个集合)车就是连接某行某列的线。
3)然后枚举删车(车就是连接两个集合的线),就是删边,如果这个边删了 最大匹配减少了,那这个边就是重要边
4)建图求最大匹配
AC代码
/*
每行每列只能放一个车,最多放车数就是 行列的最大匹配
枚举删除每个点,如果最大匹配减少 则这个点为important
*/
#include<iostream>
#include<cstring>
#include<stdio.h>
#include<math.h>
#include<queue>
#include<vector>
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e3+5;
int N, M, K;
vector<int> G[maxn];
bool Used[maxn];
int Link[maxn];
int U, V;
void init(){
U = -1, V = -1;
for(int i = 1; i <= N; ++i){
G[i].clear();
}
memset(Link, -1, sizeof(Link));
}
int Dfs(int x){
for(int i = 0; i < G[x].size(); ++i){
int v = G[x][i];
if (U == x && V == v) continue;
if (Used[v]) continue;
Used[v] = 1;
if (Link[v] == -1 || Dfs(Link[v])) {
Link[v] = x;
return true;
}
}
return false;
}
int main(){
int Cas = 0;
int r, l;
while (~scanf("%d%d%d", &N, &M, &K)) {
init();
vector< pair<int, int> > vec;
for(int i = 1; i <= K;++i){
scanf("%d%d", &r, &l);
vec.push_back(make_pair(r, l));
G[r].push_back(l);
}
int All = 0;
for(int i = 1; i <= N; i++){
memset(Used, 0, sizeof(Used));
if (Dfs(i)) {
All++;
}
}
int Ans = 0;
for (int i = 0; i < vec.size(); i++) {
U = vec[i].first;
V = vec[i].second;
int Cnt = 0;
memset(Link, -1, sizeof(Link));
for(int i = 1; i <= N; i++){
memset(Used, 0, sizeof(Used));
Cnt += Dfs(i);
}
if (Cnt < All){
Ans ++;
}
}
printf("Board %d have %d important blanks for %d chessmen.\n", ++Cas, Ans, All);
}
return 0;
}