题意:给出一张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