• [CF1354E] Graph Coloring


    Description

    给定 (n) 个点的无向图和一个整数 (k le n),要求解决一下问题中的任何一个:求一个大小恰好为 (lceil frac n 2 ceil) 的独立集;求一个大小不超过 (k) 的环。已经可以证明对于任意给定的整数 (k) 一定可以解决这两个问题中的一个。

    Solution

    由于已经保证了对于任意给定的整数 (k) 一定可以解决这两个问题中的一个,我们不妨取 (k=n),此时如果原图是一棵树,那么我们直接二分图染色即可;否则,必然有一个长度不超过 (n) 的环。

    考虑原问题,我们只需要找一个结点数为 (k) 的连通子图(由于原图是连通的所以我们一定能找到),对这个子图进行上面的求解即可。

    
    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long 
    const int N = 5005;
    
    struct Component 
    {
        vector <int> vec;
        int c0,c1;
        vector <int> vec0,vec1;
    };       
    
    vector <Component> comp;    // 连通分量
    
    vector <int> g[N];
    
    int n,m,t1,t2,t3,n1,n2,n3,vis[N],col[N],seq[N];
    bool f[N][N];
    
    vector <int> res_dfs1, res_dfs1_0, res_dfs1_1;
    
    vector <int> ans1,ans2,ans3;
    
    void findans(int i,int j)
    {
        Component &c=comp[i-1];
        if(i)
        {
            if(j>=c.c0 && f[i-1][j-c.c0])
            {
                for(int i:c.vec0)
                {
                    ans2.push_back(i);
                }
                for(int i:c.vec1)
                {
                    if(ans1.size()<n1) ans1.push_back(i);
                    else ans3.push_back(i);
                }
                findans(i-1,j-c.c0);
            }
            else if(j>=c.c1 && f[i-1][j-c.c1])
            {
                for(int i:c.vec1)
                {
                    ans2.push_back(i);
                }
                for(int i:c.vec0)
                {
                    if(ans1.size()<n1) ans1.push_back(i);
                    else ans3.push_back(i);
                }
                findans(i-1,j-c.c1);
            }
        }
    }
    
    void dfs1(int p)
    {
        vis[p]=1;
        if(col[p]==0) res_dfs1_0.push_back(p);
        if(col[p]==1) res_dfs1_1.push_back(p);
        res_dfs1.push_back(p);
        for(int q:g[p])
        {
            if(vis[q]==0)
            {
                col[q]=col[p]^1;
                dfs1(q);
            }
            else 
            {
                if(col[p]==col[q]) 
                {
                    cout<<"NO"<<endl;
                    exit(0);
                }
            }
        }
    }
    
    signed main()
    {
        ios::sync_with_stdio(false);
    
        cin>>n>>m>>n1>>n2>>n3;
        for(int i=1;i<=m;i++) 
        {
            cin>>t1>>t2;
            g[t1].push_back(t2);
            g[t2].push_back(t1);
        }
    
        // 分解每个连通分量
        for(int i=1;i<=n;i++)
        {
            if(vis[i]==0)
            {
                res_dfs1.clear();
                res_dfs1_0.clear();
                res_dfs1_1.clear();
                dfs1(i);
                comp.push_back({res_dfs1,res_dfs1_0.size(),res_dfs1_1.size(),
                                res_dfs1_0,res_dfs1_1});
            }
        }
    
        // 背包 DP 
        f[0][0]=1;
        for(int i=1;i<=comp.size();i++)
        {
            Component &c=comp[i-1];
            for(int j=c.c0;j<=n;j++) f[i][j]|=f[i-1][j-c.c0];
            for(int j=c.c1;j<=n;j++) f[i][j]|=f[i-1][j-c.c1];
        }
        
        bool flagAnswer=f[comp.size()][n2];
    
        if(flagAnswer==0) 
        {
            cout<<"NO"<<endl;
            return 0;
        }
    
        // 构造答案
        findans(comp.size(),n2);
    
        for(int i:ans1) seq[i]=1;
        for(int i:ans2) seq[i]=2;
        for(int i:ans3) seq[i]=3;
    
        cout<<"YES"<<endl;
        for(int i=1;i<=n;i++) cout<<seq[i];
        cout<<endl;
    
    }
    
  • 相关阅读:
    《一个人的村庄》 ——刘亮程
    uva 11020
    Codeforces Round #190 (Div. 2) B. Ciel and Flowers
    hdu3308 线段树——区间合并
    线段树,区间更新
    vim 被墙
    ubuntu12.04 修复Grub2
    windows下mysql数据库忘记密码
    高性能的异步爬虫
    中间件
  • 原文地址:https://www.cnblogs.com/mollnn/p/13952604.html
Copyright © 2020-2023  润新知