链接:https://ac.nowcoder.com/acm/problem/20068
前置知识点:https://wenku.baidu.com/view/07f4be196c175f0e7cd13784.html(cdq 弦图与区间图)
题目描述
K国是一个热衷三角形的国度,连人的交往也只喜欢三角原则.他们认为三角关系:即AB相互认识,BC相互认识,CA 相互认识,是简洁高效的.
为了巩固三角关系,K国禁止四边关系,五边关系等等的存在.所谓N边关系,是指N个人 A1A2 ...An之间仅存在N对认识关系:(A1A2)(A2A3)...(AnA1),而没有其它认识关系.比如四边关系指ABCD四个人 AB,BC,C D,DA相互认识,而AC,BD不认识.
全民比赛时,为了防止做弊,规定任意一对相互认识的人不得在一队,国王相知道, 最少可以分多少支队。
用最少的颜色给每个点染色使得相邻点颜色不同
诱导子图:某些点和始图中连接这些点的边
团:
完全图:每两个点都有一条边相连
单纯点:设N(v)表示与v相连的点集,一个点称为单纯点当{v}+N(v)的诱导子图是一个团
完美消除序列:一个点的序列(每个点恰好出现一次)v1,v2,v3......vn满足vi在{vi,vi+1,vi+2,......vn}的诱导子图中为一个单纯点
一个无向图是弦图当且仅当它有一个完美消除序列
最大势算法:从n到1依次给点标号(标号为i代表出现在完美消除序列的第i个)
用label[i]代表第i个点与多少已标号的点相连,每次找label[i]最大的没标号的点标号
......
本题生成一个完美消除序列,按照完美消除序列倒序遍历点,染上当前能染的最小颜色
#include<bits/stdc++.h>
#define REP(i,st,en) for(int i=st;i>=en;i--)
#define rep(i,st,en) for(int i=st;i<=en;i++)
using namespace std;
typedef long long ll;
vector<int>v;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
struct node
{
int to,next;
}e[2000100];
int n,m,x,op,a,b,cnt,head[2000100],vis[2000100],d[2000100],que[2000100],has[2000100],col[2000100],ans;
void add(int u,int v)
{e[++cnt].to=v;e[cnt].next=head[u];head[u]=cnt;}
int main()
{
scanf("%d%d",&n,&m);
while(m--)
{
a=read(),b=read();
add(a,b),add(b,a);
}
REP(i,n,1)//生成完美消除序列
{
int t=0;
for(int j=1;j<=n;j++)
if(!vis[j]&&d[j]>=d[t])
t=j;//找到没标号的最大值
vis[t]=1;que[i]=t;//加入完美消除序列
for(int j=head[t];j;j=e[j].next)
d[e[j].to]++;//连接的每个点degree++
}
REP(i,n,1)
{
int t=que[i];//在完美消除序列中从后往前遍历
for(int j=head[t];j;j=e[j].next)
has[col[e[j].to]]=i;//标记相邻点的color在第i个点不能染
int j;
for(j=1;;j++)
if(has[j]!=i)
break;
col[t]=j;//找到最小能染的color
if(j>ans)
ans=j;//记录最大的color编号,也就是数量
}
printf("%d",ans);
return 0;
}