ZOJ 1015-Fishing Net(判断弦图)

Fishing Net

Time Limit: 10 Seconds      Memory Limit: 32768 KB

In a highly modernized fishing village, inhabitants there make a living on fishery. Their major tools, fishing nets, are produced and fixed by computer. After catching fishes each time, together with plenty of fishes, they will bring back the shabby fishing nets, which might be full of leaks. Then they have to inspect those nets. If there exist large leaks, they have to repair them before launching out again.

Obviously, the smaller the leaks in the fishing nets are, the more fishes they will catch. So after coming back, those fishermen will input the information of the fishing nets into the computer to check whether the nets have leaks.

The checking principle is very simple: The computer regards each fishing net as a simple graph constructed by nodes and edges. In the graph, if any circle whose length (the number of edges) is larger than 3 must has at least one chord, the computer will output "Perfect" indicating that the fishnet has no leaks. Otherwise, "Imperfect" will be displayed and the computer will try to repair the net.

Note: A circle is a closed loop, which starts from one node, passes through other distinct nodes and back to the starting node. A chord is an edge, which connects two different nodes on the circle, but it does not belong to the set of edges on the circle.


Input

The input file contains several test cases representing different fishing nets. The last test case in the input file is followed by a line containing 0 0.

The first line of each test case contains two integers, n and m, indicating the number of nodes and edges on the net respectively, 1 <= n <= 1000. It is followed by m lines accounting for the details of the edges. Each line consists of two integers xi and yi, indicating there is an edge between node xi and node yi.


Output

For each test case, display its checking results. The word "Imperfect" suggests that the corresponding fishing net is leaking, while the word "Perfect" stands for a fishing net in good condition.

Follow the output for each net with a blank line.


Sample Input

4 4
1 2
2 3
3 4
4 1
3 3
1 2
2 3
3 1
0 0


Output for the Sample Input

Imperfect

Perfect


题意:给定一个图。判断是不是弦图?

思路:(1)神马是弦图?对于一个无向图,若该图的任意一个长度大于3的环中存在一条边连接这个环上不相邻的两点,则此图称作弦图。

(2)什么是团?团是原图的一个子图,子图就是包含了原图的某些点,那么就要包含这些点之间的边。并且团不是一般的子图而是一个完全子图,就是这个子图的任意两个顶点之间都有边。下面的ABCD就是原图的一个团。


(3)完美消除序列:原图的一个点的序列(每个点出现且恰好出现一次)v1, v2,……, vn满足{vi, vi+1,…,vn}的组成的子图为团。

(4)一个无向图是弦图当且仅当它有一个完美消除序列。

(5)如何计算完美消除序列?最大势算法: 从n到1的顺序依次给点标号(标号为i的点出现在完美消除序列的第i个)。 设label[i]表示第i个点与多少个已标号的点相 邻,每次选择label[i]最大的未标号的点进行标号。注意这里只是计算出了完美消除序列,但是在求出这个之后还没有判定是不是弦图。

(6)如何从完美消除序列判断原图是不是弦 图?最朴素的办法是依次判断 {vi+1,…,vn}中所有与vi相邻的点是否构成了一个团。可以这样优化:设{vi+1,…,vn}中所有与vi相邻的点依次为 vj1,……,vjk。只需判断vj1是否与vj2,……,vjk相邻即可。

#include<map>
#include<stack>
#include<queue>
#include<vector>
#include<math.h>
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
typedef long long  ll;
#define  maxn 1005
int flag[maxn],d[maxn],g[maxn][maxn],a[maxn],tmp[maxn];
vector<int>q[maxn];
int  main(void)
{
	int n,m,i,j,x,y,mark;
	while(scanf("%d%d",&n,&m),n!=0 && m!=0)
	{
		mark=1;
		memset(d,0,sizeof(d));
		memset(g,0,sizeof(g));
		memset(flag,0,sizeof(flag));
		for(i=1;i<=m;i++)
		{
			scanf("%d%d",&x,&y);
			g[x][y]=g[y][x]=1;
		}
		for(i=n;i;i--)
		{
			int k,u=-1;
			for(j=1;j<=n;j++)
				if(flag[j]==0 && d[j]>u)
					k=j,u=d[j];
			a[i]=k;
			flag[k]=1;
			for(j=1;j<=n;j++)
				if(flag[j]==0 && g[k][j])
					d[j]++;
		}
		for(i=1;i<=n;i++)
		{
			memset(tmp,0,sizeof(tmp));
			for(j=i+1;j<=n;j++)
				if(g[a[i]][a[j]])
					tmp[++tmp[0]]=a[j];
			for(j=2;j<=tmp[0];j++)
				if(!g[tmp[1]][tmp[j]])
					mark=0;
		}
		if(mark)
			printf("Perfect\n");
	    else
			printf("Imperfect\n");
		printf("\n");
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值