返回顶部

Codeforces Round #747 (Div. 2) D. The Number of Imposters (二分图染色)

  • 题意:有一张\(n\)个点的有向图,\(u-(I/C)>v\),表示\(u\)\(v\)\(I/C\),假如\(u\)\(C\)那么他说的是真话,否则是假话,现在要你给所有点赋值\(I/C\),问你怎么赋值才能保证合法且\(I\)的数量最大。

  • 题解\(u-(I)>v\),假如\(u\)\(I\),那么\(v\)\(I\),假如\(u\)\(C\),那么\(v\)\(C\)\(u-(C)>v\),假如\(u\)\(I\),那么\(v\)\(C\),假如\(u\)\(C\),那么\(v\)\(I\),所以我们发现,边权为\(I\)的两点必然相同,\(C\)的两点必然不同,那么连通块内的某一个点赋值后,其他点的值也就确定了,因为只有两种赋值情况,所以可以用二分图染色来写,并且注意到初始点的赋值不同,两种结果是相反的,所以我们染完色后只需取最大即可,而不用再跑一次。

  • 代码:

    #include <bits/stdc++.h>
    #define ll long long
    #define fi first
    #define se second
    #define pb push_back
    #define me memset
    #define rep(a,b,c) for(int a=b;a<=c;++a)
    #define per(a,b,c) for(int a=b;a>=c;--a)
    const int N = 1e6 + 10;
    const int mod = 1e9 + 7;
    const int INF = 0x3f3f3f3f;
    using namespace std;
    typedef pair<int,int> PII;
    typedef pair<ll,ll> PLL;
    ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
    ll lcm(ll a,ll b) {return a/gcd(a,b)*b;}
    
    int n,m;
    vector<PII> edge[N];
    char s[N];
    int color[N];
    int cnt[N];
    bool flag;
    
    void dfs(int u,int x){
        color[u]=x;
        cnt[x]++;
        for(auto to:edge[u]){
            if(color[to.fi]==-1){
               dfs(to.fi,x^to.se); 
            }
            else{
                if((to.se==0 && color[u]!=color[to.fi]) || (to.se==1 && color[u]==color[to.fi])){
                    flag=false;
                    return;
                }
            }
        }
    }
    
    int main() {
        int _;
        scanf("%d",&_);
        while(_--){
            scanf("%d %d",&n,&m);
            for(int i=1;i<=n;++i) edge[i].clear(),color[i]=-1;
            for(int i=1;i<=m;++i){
                int u,v;
                scanf("%d %d %s",&u,&v,s);
                if(!strcmp(s,"crewmate")){
                    edge[u].pb({v,0});
                    edge[v].pb({u,0});
                }
                else{
                    edge[u].pb({v,1});
                    edge[v].pb({u,1});
                }
            }
            flag=true;
            int ans=0;
            for(int i=1;i<=n;++i){
                if(color[i]==-1){
                    cnt[0]=cnt[1]=0;
                    dfs(i,0);
                    ans+=max(cnt[0],cnt[1]);
                }
            }
            if(flag) printf("%d\n",ans);
            else puts("-1");
        }
    
    	
        return 0;
    }
    
posted @ 2021-10-12 15:28  Rayotaku  阅读(90)  评论(0编辑  收藏  举报