1006: [HNOI2008]神奇的国度
思路:弦图+完美消除序列
弦图基本知识:戳戳戳!
按照完美消除序列从后向前染色,给每个点染可染颜色最小的
加上优先队列做到
O(nlogn)
既然后面的染色是O(nlogn)了,前面的MCS我们也用优先队列水吧……
代码:
我手写了两个优先队列??
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#define x first
#define y second
using namespace std;
const int MAXN=10010,MAXM=1000010;
pair<int,int> front[MAXM<<1];
int orderx[MAXM<<1],stdx[MAXN];
int n,m;
int num[MAXN];
void sortx()
{
for (int i=1;i<=m;i++)
num[front[i].x]++;
for (int i=1;i<=n;i++) {
num[i]+=num[i-1];
stdx[i]=num[i]; }
for (int i=1;i<=m;i++)
orderx[++num[front[i].x-1]]=i;
return ;
}
pair<int,int> heap[MAXN];
int ht;
int point[MAXN];
bool work[MAXN];
int mcs[MAXN];
void swapheap(int l,int r)
{
swap(heap[l],heap[r]);
point[heap[l].y]=l;
point[heap[r].y]=r;
return ;
}
void adjustdown(int x)
{
bool next=true;
while (next) {
next=false;
int l=x*2,r=x*2+1;
if (l<=ht)
if (r<=ht) {
if (heap[l]>heap[r] && heap[l]>heap[x]) {
swapheap(l,x); x=l; next=true; }
else if (heap[r]>heap[x]) {
swapheap(r,x); x=r; next=true; }}
else if (heap[l]>heap[x]) {
swapheap(l,x); x=l; next=true; }}
return ;
}
void adjustup(int x)
{
bool next=true;
while (next) {
next=false;
int f=x/2;
if (f)
if (heap[x]>heap[f]) {
swapheap(x,f); x=f; next=true; }}
return ;
}
void MCS()
{
int t=0;
ht=n;
for (int i=1;i<=ht;i++) {
heap[i].x=0; heap[i].y=n-i+1; point[n-i+1]=i; }
while (ht) {
pair<int,int> now=heap[1];
work[now.y]=true; mcs[++t]=now.y;
swapheap(1,ht); ht--; adjustdown(1);
int x=now.y;
for (int i=stdx[x-1]+1;i<=stdx[x];i++)
if (!work[front[orderx[i]].y]) {
int next=front[orderx[i]].y;
heap[point[next]].x++;
adjustup(point[next]); }}
return ;
}
int color[MAXN];
int c[MAXN];
bool in[MAXN];
void swapc(int l,int r)
{
swap(c[l],c[r]);
point[c[l]]=l;
point[c[r]]=r;
return ;
}
void cadjustdown(int x)
{
bool next=true;
while (next) {
next=false;
int l=x*2,r=x*2+1;
if (l<=ht)
if (r<=ht) {
if (c[l]<c[r] && c[l]<c[x]) {
swapc(l,x); x=l; next=true; }
else if (c[r]<c[x]) {
swapc(r,x); x=r; next=true; }}
else if (c[l]<c[x]) {
swapc(l,x); x=l; next=true; }}
return ;
}
void cadjustup(int x)
{
bool next=true;
while (next) {
next=false;
int f=x/2;
if (f)
if (c[x]<c[f]) {
swapc(x,f); x=f; next=true; }}
return ;
}
int ans;
void init()
{
cin>>n>>m;
for (int x,y,i=1;i<=m;i++) {
scanf("%d%d",&x,&y);
front[i*2-1].x=x; front[i*2-1].y=y;
front[i*2].y=x; front[i*2].x=y; }
m<<=1;
sortx();
MCS();
for (int i=1;i<=n;i++)
{ c[i]=i; point[i]=i; in[i]=true; }
ht=n;
int stack[MAXN],top=0;
for (int i=1;i<=n;i++) {
int x=mcs[i];
for (int j=stdx[x-1]+1;j<=stdx[x];j++) {
int next=front[orderx[j]].y;
int newc=color[next];
if (newc && in[newc]) {
int loc=point[newc]; in[newc]=false; stack[++top]=newc;
swapc(loc,ht); ht--; cadjustdown(loc); }}
color[x]=c[1];
ans=max(color[x],ans);
while (top) {
in[stack[top]]=true;
c[++ht]=stack[top];
point[stack[top]]=ht;
cadjustup(ht);
top--; }}
cout<<ans<<endl;
return ;
}
int main()
{
init();
return 0;
}