题意:给定一个图G,判断其是否为弦图。弦图定义:如果每个长度大于3的圈中至少有一条弦。(if any circle whose length (the number of edges) is larger than 3 must has at least one chord)。
思路:最大势(MCS)算法。(参考陈丹琦课件)。从n到1的顺序依次给顶点标号(标号i出现的点为完美消除序列中的第i个),d[i]表示第i个点与多少个已标号点相邻。每次选取d[i]最大的未标号点标号。之后,对得到的序列进行检测,看其是否确实为完美消除序列。方法为设{vi+1,vi+2...vn}中所有与vi相邻的点依次为vj1...vjk,只需判断vj1是否与vj2...vjk相邻即可。下面代码中,s数组存储的是完美消除序列,t[i]数组存储的是第i个节点在完美消除序列中的位置。
#include <stdio.h>
#include <string.h>
#define N 1005
struct edge{
int y,next;
}e[N*N];
int first[N],d[N],visited[N],s[N],t[N];
int n,m,top;
void add(int x,int y){
e[top].y = y;
e[top].next = first[x];
first[x] = top++;
}
int test(){
int i,j,min,flag[N];
for(i = 1;i<n;i++){
min = s[n];
memset(flag,0,sizeof(flag));
for(j = first[s[i]];j!=-1;j=e[j].next)
if(t[e[j].y] > t[s[i]]){//保证从vi+1...vn的这个范围内找
if(t[e[j].y] < t[min])
min = e[j].y;//找到vj1
flag[e[j].y] = 1;//flag为1的是与vi相邻的点
}
flag[min] = 0;
for(j = first[min];j!=-1;j=e[j].next)//看看vj1是否与vj2...vjn都相邻
if(flag[e[j].y])
flag[e[j].y]--;
for(j = 1;j<=n;j++)
if(flag[j])
return 0;
}
return 1;
}
int main()
{
freopen("/Users/MeichenDu/Desktop/mango/he/a.txt", "r", stdin);
while(scanf("%d %d",&n,&m) &&n&&m){
int i,j,a,b,now;
top = 0;
memset(d,0,sizeof(d));
memset(visited,0,sizeof(visited));
memset(first, -1, sizeof(first));
for(i = 0;i<m;i++){
scanf("%d %d",&a,&b);
add(a,b),add(b,a);
}
for(i = n;i>=1;i--){
now = 1;
for(j = 2;j<=n;j++)
if(!visited[j] && d[j]>d[now])
now = j;
s[i] = now;
t[now] = i;
visited[now] = 1;
for(j = first[now];!visited[e[j].y]&&j!=-1;j=e[j].next)
d[e[j].y]++;
}
if(test())
printf("Perfect\n\n");
else
printf("Imperfect\n\n");
}
return 0;
}
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- ovod.cn 版权所有 湘ICP备2023023988号-4
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务