ZOJ 1015 弦图的判断

本文介绍了一种用于判断无向图是否为弦图的有效算法。该算法通过两步完成:首先给节点进行特定编号,其次检查编号后的图是否满足弦图的定义。整个过程的时间复杂度为O(n+m),其中n为节点数,m为边数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转:

定义: 
无向图中,如果任意边数大于3的环,至少存在一条边连接环中不相邻的某两 
个点,则称此图为弦图(Chordal Graph)。 

zoj1015的题目: 
判断无向图是否为弦图,是则输出Perfect,否则输出Imperfect。 

以下是时间复杂度为O(n+m)的算法,n是图的点数,m是图的边数。 
第一步:给节点编号 
设已编号的节点集合为A,未编号的节点集合为B 
开始时A为空,B包含所有节点。 
for num=n-1 downto 0 do 

在B中找节点x,使与x相邻的在A集合中的节点数最多,将x编号为num, 
并从B移入A 

第二步:检查 
for num=0 to n-1 do 

对编号为num的节点x,设所有编号大于num且与x相邻的节点集合为C, 
在集合C中找出编号最小的节点y,如果集合C中存在不等于y的节点z, 
且y与z间没有边,则此图不是弦图,退出。 

检查完了,则此图是弦图。 

#include <iostream>
#include <cstdio>
#include <limits.h>
#include <memory.h>
using namespace std;
#define MAX 1010

bool g[MAX][MAX];
int label[MAX],temp[MAX],temp2[MAX];
int n,m;

void labeling(){
	memset(label,0,sizeof(label));
	memset(temp,0,sizeof(temp));
	for (int i=n;i>=1;--i)
	{
		int max=-1,pos=0;
		for (int j=1;j<=n;++j)
		{
			if(!label[j]&&temp[j]>max){//找结点X,使与x相邻的在A集合中的节点数最多
				max=temp[j];
				pos=j;
			}
		}
		label[pos]=i;//将x编号为num
		for (int k=1;k<=n;++k)
		{
			if(!label[k]&&(g[pos][k]||g[k][pos]))temp[k]++;//将与x相邻的点的和A集合连接的数量加一
		}
	}
}

bool check(){
	labeling();
	for (int i=n;i>=1;--i)
	{
		memset(temp2,0,sizeof(temp2));

		int minV=INT_MAX,minPos=0;

		for (int j=1;j<=n;++j)
		{
			if(g[i][j]&&label[j]>label[i])temp2[j]=label[j];//设所有编号大于num且与x相邻的节点集合为C
		}
		for (int j=1;j<=n;++j)
		{
			if(temp2[j]&&temp2[j]<minV){//找出编号最小的结点y
				minV=temp2[j];
				minPos=j;
			}
		}
		for (int j=1;j<=n;++j)
		{
			if(temp2[j]&&j!=minPos&&!g[minPos][j]&&!g[j][minPos])return false;//判断集合中是否存在如果集合C中存在不等于y的节点z, 且y与z间没有边,则此图不是弦图,退出。 
		}

	}
	return true;//检查完了就是弦图
}
int main(){
	int i;

	while (scanf("%d%d",&n,&m)==2)
	{
		if(!n&&!m)break;
		memset(g,0,sizeof(g));

		for (i=0;i<m;++i)
		{
			int u,v;

			scanf("%d%d",&u,&v);
			g[u][v]=g[v][u]=1;
		}
		if(check()){
			printf("Perfect\n\n");
		}else{
			printf("Imperfect\n\n");
		}
	}
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值