• CF1354E Graph Coloring (二分图+dp)


    对于这题,我们发现1和3点是同类点,因此其实就是二分图染色,如果只有一个连通块,那么判断一下是否是二分图就行。

    现在有多个连通块,因此我们还要判定一下能否把这些2分给这么多个连通块

    因此可以做一下背包,先存一下每个连通图的信息,之后dp,除了维护可达性,还要维护一个把图的哪部分分给2

    如果最后不能分配,输出no,然后就做一下dfs填色即可

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> pll;
    const int inf=0x3f3f3f3f;
    const int N=2e5+10;
    int n,m;
    int a,b,c,d;
    int h[N],e[N],ne[N],idx;
    int f[5010][5010];
    int cnt[2];
    int st[N],ans[N];
    vector<int> num;
    pll res[N];
    int sign[5050][5050];
    void add(int a,int b){
        e[idx]=b,ne[idx]=h[a],h[a]=idx++;
    }
    void dfs(int u,int cur){
        int i;
        cnt[cur]++;
        st[u]=cur;
        for(i=h[u];i!=-1;i=ne[i]){
            int j=e[i];
            if(st[j]==-1){
                dfs(j,1-cur);
            }
            else{
                if(st[j]==cur){
                    cout<<"NO"<<endl;
                    exit(0);
                }
            }
        }
    }
    void print(int u,int cur){
        if(cur==0){
            ans[u]=2;
        }
        else{
            if(a)
                ans[u]=1,a--;
            else
                ans[u]=3;
        }
        for(int i=h[u];i!=-1;i=ne[i]){
            int j=e[i];
            if(ans[j])
                continue;
            print(j,1-cur);
        }
    }
    int main(){
        ios::sync_with_stdio(false);
        cin>>n>>m;
        cin>>a>>b>>c;
        int i;
        memset(h,-1,sizeof h);
        memset(st,-1,sizeof st);
        while(m--){
            int x,y;
            cin>>x>>y;
            add(x,y);
            add(y,x);
        }
        for(i=1;i<=n;i++){
            if(st[i]==-1){
                cnt[0]=cnt[1]=0;
                dfs(i,0);
                num.push_back(i);
                res[i].first=cnt[0];
                res[i].second=cnt[1];
            }
        }
        f[0][res[num[0]].first]=1,sign[0][res[num[0]].first]=0;
        f[0][res[num[0]].second]=1,sign[0][res[num[0]].second]=1;
        for(i=1;i<(int)num.size();i++){
            for(int j=0;j<=b;j++){
                if(j>=res[num[i]].first&&f[i-1][j-res[num[i]].first]) f[i][j]=1,sign[i][j]=0;
                if(j>=res[num[i]].second&&f[i-1][j-res[num[i]].second]) f[i][j]=1,sign[i][j]=1;
            }
        }
        if(!f[(int)num.size()-1][b]){
            cout<<"NO"<<endl;
            return 0;
        }
        for(i=(int)num.size()-1;i>=0;i--){
            print(num[i],sign[i][b]);
            if(!sign[i][b])
                b-=res[num[i]].first;
            else
                b-=res[num[i]].second;
        }
        cout<<"YES"<<endl;
        for(i=1;i<=n;i++){
            cout<<ans[i];
        }
        cout<<endl;
        return 0;
    }
    View Code
  • 相关阅读:
    Gym
    Gym
    Gym
    LA 3713 宇航员分组
    LA 3211 飞机调度(2—SAT)
    POJ 1050 To The Max
    51nod 1050 循环数组最大子段和
    UVa 11149 矩阵的幂(矩阵倍增法模板题)
    POJ 1236 Network of School
    UVa 11324 最大团(强连通分量缩点)
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/13509502.html
Copyright © 2020-2023  润新知