您的位置:首页 > 其它

hdu 3097 The Partition of A Graph uva 11396 Claw Decomposition

2013-11-20 21:06 183 查看
这两道题比较像,就放在一起写吧。

题意:第一道题,在1000个点的无向图中,现在要把所有的边分成一对一对的,要求这一对边必须要在图中相邻,询问存不存在这样的一种划分方法。

第二道题,在400个点的图中,保证每个点的度都是3,那么现在要分成爪子的形状,就是中间一个点度为3,其他外面连接了三个点,询问能不能将图中划分成一些爪子。

想法:第一题中,如果这样考虑这个问题,将原图中的点看成边看成点,然后如果两个点是相连的,我们就加一条边,现在的问题就是看在这个1000个点中一般图最大匹配是完美匹配,但是这个时间复杂度是肯定解不出来的,那么这道题目里面有什么可以利用的性质呢,可以发现这个图是有一些特点的,因为原图中的一个点上的边是任意可以选的,所以这一部分就是完全图,整个图就是由一块块的完全图和一些公共点连接在一起组成的,把完全图部分抽象成点就可以看成一棵树,那么由因为这部分是完全图,任意两个可以匹配,所以直接看这个联通块的个数是偶数的话就可以了。

第二道题,每个点的度是3,而一个爪子中间的的度就是3,所以说这个点要么是重点,要么就是轻点,而原图中如果有两个点是相邻的,必然一个重点一个轻点,为什么(很好推),所以这不就是一个二分图模型嘛,相邻点全部在对面,假如能够形成二分图,那么两边的点数肯定是相同的,然后就是一边的全部重点,对面全部是轻点,就是爪的分解。

一下子还真没想到。。

#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <memory.h>
#include <string>

using namespace std;

int n ;
#define maxn 410
vector<int> G[maxn];

void read() {
	int m = 3 * n;
	int u, v;
	for(int i = 1;i <= n;i++)
		G[i].clear();
	while(scanf("%d%d",&u,&v), u + v) {
		G[u].push_back(v);
		G[v].push_back(u);
	}
}

int color[maxn];

bool dfs(int u,int c) {
	color[u] = c;
	int size = G[u].size();
	for(int i = 0 ;i < size;i++) {
		int v = G[u][i];
		if(color[v] == 1 - c)
			continue;
		if(-1 == color[v])
			if(false == dfs(v, 1 - c))
				return false;
		if(color[v] == c)
			return false;
	}
	return true;
}

string solve() {
	memset(color, -1, sizeof(color));
	for(int i = 1;i <= n;i++)
		if(-1 == color[i])
			if(false == dfs(i, 0))
				return "NO";
	return "YES";
}

int main() {
	freopen("D:\\in.txt","r",stdin);
	while(cin >> n ,n) {
		read();
		cout << solve() << endl;
	}
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: