bzoj4878: [Lydsy2017年5月月赛]挑战NP-Hard

传送门
考试的时候完全想不出来。
考虑尝试对图进行贪心染色,col[x]=mex(col[y]),其中x与y有边,且y已被染过色
若max(col[i])<=k,那么k染色问题就解决了
否则随便选一个颜色是k+1的点,按照颜色递减走,一定可以走出一条边数为k的简单路径
因为如果一个点col是x,在x!=1是,必然有一个与其相邻的点y满足col[y]=x-1(否则这个点的col值就可以取到x-1)了。
时间复杂度O(n+m)

#include<map>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 1010
#define M 20202
using namespace std;
int T,tot,n,m,k,x,y,fl,pos;
int head[N],vis[N],col[N];
struct edge{int to,next;}e[M];
void add(int x,int y){
    e[++tot]=(edge){y,head[x]};
    head[x]=tot;
}
void dfs(int x){
    pos++;
    for (int i=head[x];i;i=e[i].next)
        if (col[e[i].to])
            vis[col[e[i].to]]=pos;
    for (int i=1;;i++)
        if (vis[i]<pos){
            col[x]=i; break;
        }
    for (int i=head[x];i;i=e[i].next)
        if (!col[e[i].to])
            dfs(e[i].to); 
}
void solve(){
    scanf("%d%d%d",&n,&m,&k);
    tot=0;
    for (int i=1;i<=n;i++) head[i]=col[i]=0;
    for (int i=1;i<=m;i++){
        scanf("%d%d",&x,&y);
        add(x,y); add(y,x);
    }
    for (int i=1;i<=n;i++)
        if (!col[i]) dfs(i);
    fl=1;
    for (int i=1;i<=n&&fl;i++)
        if (col[i]>k) fl=0;
    if (fl){
        printf("color");
        for (int i=1;i<=n;i++) printf(" %d",col[i]);
        puts("");
        return;
    }
    for (int i=1;i<=n;i++)
        if (col[i]==k+1){
            x=i; break;
        }
    printf("path");
    for (int i=1;i<=k+1;i++){
        printf(" %d",x);
        for (int j=head[x];j;j=e[j].next)
            if (col[e[j].to]==col[x]-1){
                x=e[j].to; break;
            }
    }
    puts("");
}
int main(){
    scanf("%d",&T);
    while (T--) solve();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值