zoukankan      html  css  js  c++  java
  • 二分图+dp——cf1354E

    /*
    先把点分联通块,做出二分图
    二分图一侧染1,3,另一侧染2
    分组背包求n2的可行方案 
    */
    #include<bits/stdc++.h>
    using namespace std;
    #define N 5005
    #define M 100005
     
    int n,m,n1,n2,n3; 
    vector<int>G[N];
     
    int vis[N],cnt,flag;
    vector<int>s[N][3];
    void dfs(int u,int c){
        vis[u]=c;
        s[cnt][c].push_back(u);
        
        int cc;
        if(c==1)cc=2;else cc=1;    
        for(auto v:G[u]){
            if(!vis[v])dfs(v,cc);
            else if(vis[v]==vis[u]){
                flag=1;
                return;
            }
        }
    }
     
    int useless[N][N],dp[N][N],ans[N];
     
    int main(){
        cin>>n>>m;cin>>n1>>n2>>n3;
        for(int i=1;i<=m;i++){
            int u,v;scanf("%d%d",&u,&v);
            G[u].push_back(v);
            G[v].push_back(u);
        }
        for(int i=1;i<=n;i++)if(!vis[i]){
            ++cnt;
            dfs(i,1);
            if(flag){puts("NO");return 0;}
        }
        
        dp[0][0]=1;
        for(int i=1;i<=cnt;i++){
            for(int j=s[i][1].size();j<=n2;j++)
                dp[i][j]|=dp[i-1][j-s[i][1].size()];
            for(int j=s[i][2].size();j<=n2;j++)
                dp[i][j]|=dp[i-1][j-s[i][2].size()];
        }
        if(!dp[cnt][n2]){puts("NO");return 0;}
        int now=n2,t=cnt;
        while(t){
            if(now>=s[t][1].size() && dp[t-1][now-s[t][1].size()]){
                now-=s[t][1].size();
                for(auto x:s[t][1])ans[x]=2;
                s[t][1].clear();
            }
            else if(now>=s[t][2].size() && dp[t-1][now-s[t][2].size()]){
                now-=s[t][2].size();
                for(auto x:s[t][2])ans[x]=2;
                s[t][2].clear();
            }
            t--;
        }
        if(now){
            puts("NO");return 0;
        }
        for(int i=1;i<=cnt;i++){
            if(s[i][1].size()){
                for(auto x:s[i][1])
                    if(n1)ans[x]=1,n1--;
                    else ans[x]=3;
            }else {
                for(auto x:s[i][2])
                    if(n1)ans[x]=1,n1--;
                    else ans[x]=3;
            }
        }
        puts("YES");
        for(int i=1;i<=n;i++)cout<<ans[i];
        
    }
  • 相关阅读:
    为初次使用linux设置 root密码
    linux如何改为汉化环境
    Linux 标准目录结构
    常用linux terminal 命令
    jquery 获取及设置input各种类型的值
    使用$.getJSON实现跨域ajax请求
    react 异步取数据
    PHP 全局变量
    PHP保存本地日志文件
    全端开发——css(选择器)
  • 原文地址:https://www.cnblogs.com/zsben991126/p/12918713.html
Copyright © 2011-2022 走看看