诱导子图:子图中任意一条边的两个端点一定也都在这个子图中
最大团:团中任意两点之间一定都有边,而包含顶点最多的团就是最大团
最小团覆盖:用最少的团覆盖图中所有的点
最大独立集:独立集中任意两点之间一定都没有边,而包含顶点最多的独立集就是最大独立集
最小染色:用最少的颜色给图染色使得图中任意相邻的两点颜色不相同
弦图:无向图中任意长度大于3的环都至少有一个弦,所谓弦就是连接环中不相邻两点的边
一般来讲:
①最大团数<=最小染色数
②最大独立集<=最小团覆盖
对于弦图来讲:
①最大团数==最小染色数
②最大独立集==最小团覆盖
单纯点:如果与顶点V相邻的所有点能构成一个团,那么V就是个单纯点
③任何一个弦图都有至少一个单纯点,不是完全图的弦图至少有两个不相邻的单纯点
完美消除序列:一个点的序列(每个点刚好出现1次)v1, v2,…,vn满足vi在诱导子图{vi, vi+1,…,vn}中为一个单纯点
④一个无向图是弦图的充要条件是存在完美消除序列
参考文献:https://wenku.baidu.com/view/陈丹琦.html
1006: [HNOI2008]神奇的国度
Time Limit: 20 Sec Memory Limit: 162 MBSubmit: 3762 Solved: 1725
[ Submit][ Status][ Discuss]
Description
K国是一个热衷三角形的国度,连人的交往也只喜欢三角原则.他们认为三角关系:即AB相互认识,BC相互认识,CA相互认识,是简洁高效的.为了巩固三角关系,K国禁止四边关系,五边关系等等的存在.所谓N边关系,是指N个人 A1A2...An之间仅存在N对认识关系:(A1A2)(A2A3)...(AnA1),而没有其它认识关系.比如四边关系指ABCD四个人 AB,BC,CD,DA相互认识,而AC,BD不认识.全民比赛时,为了防止做弊,规定任意一对相互认识的人不得在一队,国王相知道,最少可以分多少支队。
Input
第一行两个整数N,M。1<=N<=10000,1<=M<=1000000.表示有N个人,M对认识关系. 接下来M行每行输入一对朋友
Output
输出一个整数,最少可以分多少队
Sample Input
Sample Output
题目可以翻译为:用最少的颜色给弦图染色使得任意相邻的两点颜色不相同,即求最大团数
方法:求出完美消除序列然后暴力染色
可以使用MCS算法:
①从n到1的顺序依次给每个点标号
②lab[i]表示已经标号的点中有多少个与i相连,每次选择最大的lab[]进行标号
SA[i] = k表示标号为i的点是第k个点
然后就可以开始染色了,无脑从标号高的点开始染色即可
附录:如何判断是不是弦图?
求出完美消除序列然后看这个是不是完美消除序列(完美消除序列是否存在?)
判断方法:设{vi+1,vi+2,…,vn}中所有与vi相连的点依次为vj1, vj2,…
只需要判定vj1是否与vj2, vj3,…相邻即可
#include<stdio.h>
#include<string.h>
#include<queue>
#include<vector>
using namespace std;
int n, m, label[10005], R[10005], SA[10005];
vector<int> G[10005];
priority_queue<pair<int, int> > q;
void Color(int u)
{
int i, v;
for(i=0;i<G[u].size();i++)
{
v = G[u][i];
if(label[v]==-1)
continue;
R[label[v]] = u;
}
for(i=1;label[u]==-1;i++)
{
if(R[i]!=u)
label[u] = i;
}
}
int main(void)
{
int i, u, v, id, now, ans;
while(scanf("%d%d", &n, &m)!=EOF)
{
while(q.empty()==0)
q.pop();
for(i=1;i<=n;i++)
G[i].clear();
while(m--)
{
scanf("%d%d", &u, &v);
G[u].push_back(v);
G[v].push_back(u);
}
memset(R, -1, sizeof(R));
memset(label, 0, sizeof(label));
for(i=1;i<=n;i++)
q.push(make_pair(0, i));
for(id=n;id>=1;)
{
now = q.top().second;
q.pop();
if(R[now]!=-1)
continue;
SA[id] = now;
R[now] = id--;
for(i=0;i<G[now].size();i++)
{
u = G[now][i];
if(R[u]!=-1)
continue;
label[u]++;
q.push(make_pair(label[u], u));
}
}
memset(R, -1, sizeof(R));
memset(label, -1, sizeof(label));
for(i=n;i>=1;i--)
Color(SA[i]);
ans = 0;
for(i=1;i<=n;i++)
ans = max(ans, label[i]);
printf("%d\n", ans);
}
return 0;
}