K - Tourists' Tour(图染色)

原题: http://codeforces.com/gym/102006/problem/K

题意: n个数,每个数会往左右最近的比它大的数连边,要求直接相连的点不能染相同颜色,问最小的颜色数量。

解析:

直接连边暴力染色即可。这个如果建树的话,就是笛卡尔树加上一些边,画出来一定是很多个三角形拼起来,那么显然最后的答案最多只有3。

不知道是不是oj的问题,不同的连边方式就错了。。。

#include<bits/stdc++.h>
using namespace std;

#define rep(i,a,b) for(int i=(int)(a);i<=(int)(b);++i)
#define repp(i,b,a) for(int i=(int)(b);i>=(int)(a);--i)
const int maxn=1e6+6;
int a[maxn];
int sta[maxn],top;

int head[maxn],to[maxn<<2],nex[maxn<<2],now;
void Add(int a,int b){
    //if(a<b)printf("add %d %d\n",a,b);
    nex[++now]=head[a];head[a]=now;to[now]=b;
}

int c[maxn];
bool v[4];
void dfs(int p){
    if(c[p])return;
    rep(i,1,3)v[i]=0;
    for(int i=head[p];i;i=nex[i]){
        int u=to[i];
        if(c[u]){
            v[c[u]]=1;
        }
    }
    rep(i,1,3){
        if(!v[i]){
            c[p]=i;break;
        }
    }
    for(int i=head[p];i;i=nex[i]){
        int u=to[i];
        if(!c[u]){
            dfs(u);
        }
    }
}

int main(){
    //freopen("tour.in","r",stdin);
    ios::sync_with_stdio(false);
    cin.tie(0);
    int t;cin>>t;++t;
    while(--t){
        now=0;
        int n;cin>>n;
        rep(i,1,n)c[i]=0,head[i]=0;
        rep(i,1,n)cin>>a[i];
        top=0;
        rep(i,1,n){
            while(top&&a[sta[top]]<a[i]){
                    //Add(sta[top],i),Add(i,sta[top]);
                --top;
            }
            if(top)Add(sta[top],i),Add(i,sta[top]);//将这一行换成上面那行就错了,莫名其妙
            sta[++top]=i;
        }

        top=0;
        repp(i,n,1){
            while(top&&a[sta[top]]<a[i]){
                    //Add(sta[top],i),Add(i,sta[top]);
                --top;
            }
            if(top)Add(sta[top],i),Add(i,sta[top]);
            sta[++top]=i;
        }

        rep(i,1,n)
            dfs(i);
        int ans=1;
        rep(i,1,n)ans=max(ans,c[i]);
        cout<<ans<<endl;
        rep(i,1,n){
            cout<<c[i]<<(i==n?'\n':' ');
        }
    }
}


猜你喜欢

转载自blog.csdn.net/jk_chen_acmer/article/details/89355379
k