标签:
题意:给出一张n*n的图,里面有k个危险的点(不会翻译),每次攻击可以破坏一行或者一列里面的点,问最少攻击几次能把这些点都破坏了。
解法:一开始写了个贪心……果断wa了……后来查说是匈牙利,首先建图,行和列为点,危险的点为边,构成一个二分图,答案即为最小覆盖点,而二分图的最小覆盖点就是最大匹配,最小覆盖点(我理解)的含义是最少选几个点能使所有的边都和这些点相连,而最大匹配是最多能选出几条边,使任何一个点连的边都不超过1条,至于为啥他俩的值相等就没研究了……然后学了学原理在红书上找了份代码……
代码:
#include<stdio.h> #include<iostream> #include<algorithm> #include<string> #include<string.h> #include<math.h> #include<limits.h> #include<time.h> #include<stdlib.h> #include<map> #include<queue> #include<set> #include<stack> #include<vector> #define LL long long using namespace std; int n, k; vector <int> g[1050]; int from[1050], tot; bool use[1050]; bool match(int x) { for(int i = 0; i < g[x].size(); i++) if(!use[g[x][i]]) { use[g[x][i]] = true; if(from[g[x][i]] == -1 || match(from[g[x][i]])) { from[g[x][i]] = x; return true; } } return false; } int hungary() { tot = 0; memset(from, 255, sizeof from); for(int i = 1; i <= n; i++) { memset(use, 0, sizeof use); if(match(i)) tot++; } return tot; } int main() { while(~scanf("%d%d", &n, &k)) { for(int i = 0; i < k; i++) { int x, y; scanf("%d%d", &x, &y); y += n; g[x].push_back(y); g[y].push_back(x); } printf("%d\n", hungary()); } return 0; }
标签:
原文地址:http://www.cnblogs.com/Apro/p/4852797.html