題目來源:HDU 1281 棋盤游戲
題意:有一些點可以放車 放的時候不能相互攻擊到 求出哪一些點必須放 不放就不能得到最大的匹配
思路:行列匹配 矩陣的每一個點對於二分圖的每一條邊 首先求出最大匹配ans 然後如果每次去掉一個點然後再重新求最大匹配 很耗時 可以把第一次二分匹配的圖存著
然後那些關鍵點肯定是是匹配的邊 枚舉去掉那一個格點(就是去掉一條已經匹配邊)如果還能匹配 那麼該格點就不是關鍵點 關鍵就是不要每次重新再求最大匹配
#include#include #include using namespace std; const int maxn = 110; const int maxm = 10010; bool vis[maxn]; int y[maxn]; int n, m; int a[maxn][maxn]; int b[maxn]; bool dfs(int u) { for(int i = 0; i < m; i++) { int v = i; if(vis[v] || !a[u][i]) continue; vis[v] = true; if(y[v] == -1 || dfs(y[v])) { y[v] = u; return true; } } return false; } int match() { int ans = 0; memset(y, -1, sizeof(y)); for(int i = 0; i < n; i++) { memset(vis, false, sizeof(vis)); if(dfs(i)) ans++; } return ans; } int main() { int cas = 1; int T; int k; //scanf("%d", &T); while(scanf("%d %d %d", &n, &m, &k) != EOF) { memset(a, 0, sizeof(a)); memset(b, 0, sizeof(b)); while(k--) { int u, v; scanf("%d %d", &u, &v); u--; v--; a[u][v] = 1; } int ans = match(); int sum = 0; for(int i = 0; i < m; i++) { memset(b, 0, sizeof(b)); for(int j = 0; j < m; j++) if(y[j] != -1) b[y[j]] = 1; if(y[i] == -1) continue; int temp = y[i]; y[i] = -1; a[temp][i] = 0; b[temp] = 0; int flag = 0; for(int j = 0; j < n; j++) { memset(vis, 0, sizeof(vis)); if(!b[j] && dfs(j)) flag = 1; if(flag) break; } if(!flag) { sum++; y[i] = temp; } a[temp][i] = 1; } printf("Board %d have %d important blanks for %d chessmen.\n", cas++, sum, ans); } return 0; }