链接:http://acm.scu.edu.cn/soj/problem.action?id=4439
frog has a graph with n
vertices v(1),v(2),…,v(n) and m edges (v(a1),v(b1)),(v(a2),v(b2)),…,(v(am),v(bm)).
She would like to color some vertices so that each edge has at least one colored vertex.
Find the minimum number of colored vertices.
Input
The input consists of multiple tests. For each test:
The first line contains 2
integers n,m ( 2≤n≤500,1≤m≤n(n−1)2 ). Each of the following m lines contains 2 integers ai,bi ( 1≤ai,bi≤n,ai≠bi,min{ai,bi}≤30)
Output
For each test, write 1
integer which denotes the minimum number of colored vertices.
Sample Input
3 2
1 2
1 3
6 5
1 2
1 3
1 4
2 5
2 6
Sample Output
1
2
题意:有n个点m条边,每条边至少有一个顶点染色,至少要染多少个点
思路:二分图最小点覆盖,有一个公式 二分图最大匹配=最小点覆盖,匈牙利算法一代就出来了
比赛的时候想到这个公式了,也想到匈牙利了,就是没想明白是不是二部图,现在只感觉自己宛如一个zz
代码:(就是模板)
#include<iostream>
#include<stdlib.h>
#include<stdio.h>
#include<cmath>
#include<algorithm>
#include<string>
#include<string.h>
#include<set>
#include<queue>
#include<stack>
#include<vector>
#include<functional>
#include<map>
using namespace std;
const int INF = (int)1e9;
const int maxn = 100000 + 10;
typedef long long LL;//视情况定类型
int n, m;
vector<int>G[maxn];
bool inpath[maxn];//标记
int match[maxn];//记录匹配对象
void init()
{
memset(match, -1, sizeof(match));
memset(inpath, false, sizeof(inpath));
for (int i = 0; i < maxn; i++) {
G[i].clear();
}
}
bool findpath(int k) {
for (int i = 0; i < G[k].size(); i++) {
int v = G[k][i];
if (!inpath[v]) {
inpath[v] = true;
if (match[v] == -1 || findpath(match[v])) {//递归
match[v] = k;//即匹配对象是“k妹子”的
return true;
}
}
}
return false;
}
void hungary() {
int cnt = 0;
for (int i = 1; i <= n; i++) { //n为需要匹配的“妹子”数
memset(inpath, false, sizeof(inpath));//每次都要初始化
if (findpath(i)) cnt++;
}
cout << cnt/2 << endl;
}
int main() {
while (scanf("%d %d", &n, &m) != EOF) {
init();
for (int i = 1; i <= m; i++) {
int a, b;
scanf("%d %d", &a, &b);
G[a].push_back(b);
G[b].push_back(a);
}
hungary();
}
system("pause");
return 0;
}