zoukankan      html  css  js  c++  java
  • [Atcoder Grand Contest 006 F][AGC006F] Blackout [染色]

    题面

    传送门

    思路

    首先,这个涂黑的方法我们来优化一下模型(毕竟当前这个放到矩形里面,你并看不出来什么规律qwq)

    我们令每个行/列编号为一个点,令边(x,y)表示一条从x到y的有向边

    那么显然只要有一条长度为2的路径,就会得到一个三元环

    我们考虑如何统计新加入的边的数量,发现有如下规律:

    1.如果一个弱联通块中的点可以被3染色(0的出边染成1,1的染成2,2的染成0,倒着染就是反过来),那么这个联通块中所有0会向所有1连边,所有1会向所有2连边,所有2会向0连边

    2.如果一个弱联通块染色的时候会遇到一个点染了2种颜色,那么这个联通块会变成一个团(一个有向完全图)

    3.如果一个弱联通块染完色了,只用了1或者2种颜色,那么这个联通块不会增加新的边

    然后这题就做完了

    Code

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<cstdio>
    #include<cmath>
    #include<cassert>
    #define ll long long
    using namespace std;
    inline int read(){
        int re=0,flag=1;char ch=getchar();
        while(ch>'9'||ch<'0'){
            if(ch=='-') flag=-1;
            ch=getchar();
        }
        while(ch>='0'&&ch<='9') re=(re<<1)+(re<<3)+ch-'0',ch=getchar();
        return re*flag;
    }
    int n,m,first[100010],cnte=-1,col[100010],vis[200010];ll cnt[3],cntn,cntm;
    struct edge{
        int to,next;
    }a[200010];
    inline void add(int u,int v){
        a[++cnte]=(edge){v,first[u]};first[u]=cnte;
        a[++cnte]=(edge){u,first[v]};first[v]=cnte;
    }
    bool dfs(int u,int f,int type){
        int i,v,re=1,w;col[u]=(col[f]+type+3)%3;cnt[col[u]]++;cntn++;
        for(i=first[u];~i;i=a[i].next){
            v=a[i].to;w=(i%2?1:-1);
            if(vis[i]||vis[i^1]) continue;
            else cntm++,vis[i]=vis[i^1]=1;
            if(col[v]==-1) re&=dfs(v,u,w);
            else{
                if(col[v]!=(col[u]+w+3)%3) re=0,cnt[0]=cnt[1]=cnt[2]=1e9;
            }
        }
        return re;
    }
    int main(){
        memset(first,-1,sizeof(first));
        n=read();m=read();int i,t1,t2;ll ans=0;
        for(i=1;i<=m;i++){
            t1=read();t2=read();
            add(t1,t2);
        }
        memset(col,-1,sizeof(col));
        for(i=1;i<=n;i++){
            if(~col[i]) continue;
            memset(cnt,0,sizeof(cnt));cntn=cntm=0;
            if(dfs(i,0,1)){
                if(!cnt[0]||!cnt[1]||!cnt[2]) ans+=cntm;
                else ans+=cnt[0]*cnt[1]+cnt[1]*cnt[2]+cnt[2]*cnt[0];
            }
            else{
                if(!cnt[0]||!cnt[1]||!cnt[2]) ans+=cntm;
                else ans+=cntn*cntn;
            }
        } 
        cout<<ans;
    }
    
  • 相关阅读:
    6-Python爬虫-分布式爬虫/Redis
    ES 查询时 排序报错(fielddata is disabled on text fileds by default ... )解决方法
    Intellij Idea webstorm 激活
    Intellij Idea 配置jdk
    java 获取(格式化)日期格式
    js 跳转 XSS漏洞 预防
    CSS去掉背景颜色
    js对象无法当成参数传递 解决方法
    Elasticsearch java api
    java多条件查询SQL语句拼接的小技巧
  • 原文地址:https://www.cnblogs.com/dedicatus545/p/9602864.html
Copyright © 2011-2022 走看看