无向图的完美消除序列 判断弦图 ZOJ 1015 Fish net

   ZOJ1015

题意简述:给定一个无向图,判断是否存在一个长度大于3的环路,且其上没有弦(连接环上不同两点的边且不在环上)。

命题等价于该图是否存在完美消除序列。

所谓完美消除序列:在 vi,vi+1,...vn vi与之后与vi相邻的点构成一个团(完全子图)。

求完美消除序列的MCS算法。倒序给点标号,标号为i的点出现在序列的第i项。对每个顶点i,维护标号label[i],表示标号的度,每次选择标号最大的点标号。用堆加速。

求出了完美消除序列后,只要判断这个序列是否合法就可以得出结论。

在 vi,vi+1,...vn的导出子图中找到与vi相邻的标号最小(度最小)的点,设为vj,再检查vj是否与每个vi的邻接点相邻。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#include<algorithm>
#include<set>
#define clr(x,y) memset(x,y,sizeof(x))
using namespace std;
const int maxn=1010;

vector<int> construct(int n,vector<int> adj[maxn])
{
 static int rank[maxn],label[maxn];
 clr(rank,-1);clr(label,0);
 priority_queue<pair<int,int> > heap;

 for(int i=1;i<=n;i++)
 	heap.push(make_pair(0,i));

 for(int i=n-1;i>=0;i--)
 	{
 	 while(true)
 	 	{
 	 	 int u=heap.top().second;heap.pop();
 	 	 if(rank[u]==-1)
 	 	 	{
 	 	 	 rank[u]=i;
 	 	 	 for(vector<int>:: iterator iter=adj[u].begin();iter!=adj[u].end();++iter)
 	 	 	 	{
 	 	 	 	 if(rank[*iter]==-1)
 	 	 	 	 	{
 	 	 	 	 	 label[*iter]++;
 	 	 	 	 	 heap.push(make_pair(label[*iter],*iter));
					}
				}
			 break;
			}
		}
	}
 vector<int> result(n);
 for(int i=1;i<=n;i++)
 	{
 	 result[rank[i]]=i;
	}
 return result;
}

bool check(int n,vector<int>adj[maxn],vector<int> ord)
{
 static bool mark[maxn];
 static int rank[maxn];
 for(int i=0;i<n;i++)rank[ord[i]]=i;
 clr(mark,0);
 for(int i=0;i<n;i++)
    {
     vector<pair<int,int> >tmp;
     for(vector<int>::iterator iter=adj[ord[i]].begin();iter!=adj[ord[i]].end();++iter)
     	 if(!mark[*iter])tmp.push_back(make_pair(rank[*iter],*iter));

 sort(tmp.begin(),tmp.end());
 if(tmp.size())
 	{
 	 int u=tmp[0].second;set<int> tmpAdj;
 	 for(vector<int>::iterator iter=adj[u].begin();iter!=adj[u].end();++iter)
 	 	{
 	 	 tmpAdj.insert(*iter);
		}
	 for(int i=1;i<(int)tmp.size();++i)
	 	{
	 	 if(!tmpAdj.count(tmp[i].second))return false;
		}
	}
 mark[ord[i]]=true;
}
return true;
}

bool is_chordal(int nodeCount,vector<pair<int,int> >edges)
{
 int n=nodeCount;
 vector<int>adj[maxn];
 for(int i=0;i<=n;i++)
 	adj[i].clear();
 for(vector<pair<int,int> >::iterator iter=edges.begin();iter!=edges.end();++iter)
 	{
 	 adj[iter->first].push_back(iter->second);
 	 adj[iter->second].push_back(iter->first);
	}
 return check(n,adj,construct(n,adj));
}

int main()
{
 int n,m;
 while(scanf("%d%d",&n,&m))
 	{
 	 if(n==0&&m==0)return 0;
 	 vector<pair<int,int> >ed;
 	 for(int i=0;i<m;i++)
 	 	{
 	 	 int a,b;
 	 	 scanf("%d%d",&a,&b);
 	 	 ed.push_back(make_pair(a,b));
		}
	 if(is_chordal(n,ed))printf("Perfect\n\n");
	 	else printf("Imperfect\n\n");
	}
 return 0;
}

  完美消除序列还有广泛的应用,以后来补充。

时间: 2024-08-21 23:51:46

无向图的完美消除序列 判断弦图 ZOJ 1015 Fish net的相关文章

ZOJ 1015 Fishing Net(判断弦图)

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=15 题意:给定一个图.判断是不是弦图? 思路:(1)神马是弦图?对于一个无向图,若该图的任意一个长度大于3的环中存在一条边连接这个环上不相邻的两点,则此图称作弦图. (2)什么是团?团是原图的一个子图,子图就是包含了原图的某些点,那么就要包含这些点之间的边.并且团不是一般的子图而是一个完全子图,就是这个子图的任意两个顶点之间都有边.下面的ABCD就是原图的一个团. (

弦图 完美消除序列 MCS算法

对于普通图的两个性质: 最大团数 ≤ 最小色数 最大独立集 ≤ 最小团覆盖 而在弦图就变成了: 最大团数=最小色数 最大独立集=最小团覆盖 (虽然不知道有什么用 完美消除序列: 对与序列中的点vi,排在vi后面并且和vi相连的点是一个团 一个图存在完美消除序列是它是弦图的充要条件 那么完美消除序列有什么用呢?用处可大啦 求弦图的最大团数/最小色数的时候,只要在完美消除序列上从后往前贪心染色即可. 而求最大独立集/最小团覆盖的时候,只要在完美消除序列上从前往后贪心取点即可. 那么就来了一系列的问题

bzoj 1006: [HNOI2008]神奇的国度 弦图的染色问题&amp;&amp;弦图的完美消除序列

1006: [HNOI2008]神奇的国度 Time Limit: 20 Sec  Memory Limit: 162 MBSubmit: 1788  Solved: 775[Submit][Status] Description K国是一个热衷三角形的国度,连人的交往也只喜欢三角原则.他们认为三角关系:即AB相互认识,BC相互认识,CA相互认识,是简洁高效的.为了巩固三角关系,K国禁止四边关系,五边关系等等的存在.所谓N边关系,是指N个人 A1A2...An之间仅存在N对认识关系:(A1A2)

ZOJ 1015 Fishing Net(弦图判定)

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

弦图小结

CDQ的论文 Click Here 以下纯属复制论文,避免以后再看一次 一些概念 子图 点集和边集都是原图的子集的图 诱导子图 是子图,不含其它边 团 子图,并且是完全图 极大团 不是任何一个团的子图 最大团 点数最多的团 最小染色 用最少的颜色染给每个点,使相邻点不同色 最大独立集 不相邻的最大点集 最小团覆盖 最少的团覆盖所有点 显然的结论 团数\(\le\)色数 最大独立集\(\le\)最小团覆盖 弦 连接环内两个不相邻的点的边 弦图 任意大于三的环都至少有一条弦 结论1 弦图的诱导子图是

ZOJ 1015 Fishing Net 弦图MCS

一个无向图是弦图当且仅当有一个完美消除序列. MCS最大势:http://wenku.baidu.com/view/07f4be196c175f0e7cd13784.html 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 too

弦图与区间图

原来想把论文里面所有没证的东西都证一遍,结果发现我太弱证不了[捂脸熊]那就把一些结论记一下吧QAQ以后有什么兴趣的话再来补证明 一些定义什么的自行脑补吧 1.对任意的一张图来说,团数<=色数,最大独立集数<=最小团覆盖数.当图是弦图的时候这两个式子都取到了等号. 2.一张图是弦图当且仅当它有一个完美消除序列. 3.最大势算法(MCS)求一张弦图的完美消除序列.从n到1的顺序给每个点标号,设label[i]表示i与多少个已经标号的节点标号.那么每次选择label[i]最大点进行标号. mlogn

[BZOJ 1006] [HNOI2008] 神奇的国度 【弦图最小染色】

题目链接: BZOJ - 1006 题目分析 这道题是一个弦图最小染色数的裸的模型. 弦图的最小染色求法,先求出弦图的完美消除序列(MCS算法),再按照完美消除序列,从后向前倒着,给每个点染能染的最小颜色. 求出的颜色数就是最小染色,同时也是最大团. 代码 #include <iostream> #include <cstdlib> #include <cstdio> #include <cmath> #include <cstring> #in

BZOJ 1006 神奇的国度(弦图的染色数)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1006 题意:给定一个弦图,求最小染色数.就是用最小数目的颜色进行染色使得任意两个相邻的节点颜色不同. 思路:(1)求出弦图的完美消除序列. (2)贪心染色.从后向前用可以用的编号最小的颜色染色.在这里因为最小染色等于最大团,我直接求的最大团.为什么最小染色等于最大团呢?最大团w(G) 是包含点数最多的团,最小染色x(G)是相邻点不同色的最小颜色个数.那么w(G)<=x(G),因为最大团