scu4439 Vertex Cover(二分图最小点覆盖 匈牙利)

链接: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 ( 2n500,1mn(n1)2 ). Each of the following m lines contains 2 integers ai,bi ( 1ai,bin,aibi,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;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值