• 2017国家集训队作业[agc006f]Blackout


    2017国家集训队作业[agc006f]Blackout

    题意:

    有一个(N*N)的网格,一开始有(M)个格子被涂黑,给出这(M)个格子,和染色操作:如果有坐标为((x,y),(y,z))的格子已被染黑,那么就可以染黑坐标为((y,z))的格子。问操作到不能再操作的时候,网格里有多少个黑格子?((1le N,Mle 10^5),最开始给出的(M)个坐标互不相同)

    题解:

    在场上签到签了两个小时,看到这题一脸懵逼。= =!大概想到是把形如((x,y),(y,z))格子之间连一条边,然后会产生个新点之类的。现在想想,这样的空间复杂度完全不对了,做法不可能是这个。(然而我在场上想到这的时候,决定去打暴力了)

    每个(OIer)肯定做过一题,就是在网格上求某种合法方案,使得同一行、同一列只能有一个点。二分图匹配,对吧。那里选一个点等于行号同列之间连一条边。这题也是这样的模型。

    把所有初始涂黑的点的行号同列号之间连一条单向边,那么所有点组成了若干个弱联通块,如果有边(x ightarrow y,y ightarrow z),就会产生(z ightarrow x)的边,这样,我们发现一次操作一定生成了一个三元环,三染色。。。。。。。。不妨设染色顺序为(0,1,2)

    三种情况:

    (1.)如果三种颜色没法全部用到,那么说明当前弱联通块无法进行操作。那么它对答案的贡献就是弱联通块的边数。

    (2.)如果三种颜色全部用到了,但是存在某两个同颜色的点之间有边,那么说明这个弱联通块出现了环,稍微画画就能得出这个弱联通块最后一定会成为一个完全图,贡献为点数的平方。

    (3.)其它情况,贡献为:颜色为颜色为(0)的点数(*)颜色为(1)的点数(+)颜色为(1)的点数(*)颜色为(2)的点数(+)颜色为(2)的点数(*)颜色为(0)的点数。

    一名签到和暴力选手的啰嗦题解。。。

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define fo(i,l,r) for(ll i=l;i<=r;i++)
    #define of(i,l,r) for(ll i=l;i>=r;i--)
    #define fe(i,u) for(ll i=head[u];i;i=e[i].next)
    using namespace std;
    typedef long long ll;
    inline ll rd()
    {
        static ll x,f;
        x=0,f=1;
        char ch=getchar();
        for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
        for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
        return x*f;
    }
    const ll N=100010;
    struct edge{
    	ll v,ty,next;
    	edge(ll v=0,ll ty=0,ll next=0):v(v),ty(ty),next(next){}
    }e[N<<1];
    ll n,m,col[N],cnt[3],siz;
    ll tot=0,head[N];
    bool flag;
    
    inline void add(ll u,ll v,ll ty){e[++tot]=edge(v,ty,head[u]);head[u]=tot;}
    
    void dfs(ll u)
    {
    	cnt[col[u]]++;
    	fe(i,u){
    		ll v=e[i].v,ty=e[i].ty;
    		siz+=(ty==1);
    		if(~col[v])flag|=(col[v]!=(col[u]+ty)%3);
    		else col[v]=(col[u]+ty)%3,dfs(v);
    	}
    }
    
    int main()
    {
    	#ifndef ONLINE_JUDGE
    	freopen("inb.txt","r",stdin);
    	#endif
    	n=rd();m=rd();
    	fo(i,1,m){
    		ll x=rd(),y=rd();
    		add(x,y,1);add(y,x,2);
    	}
    	memset(col,-1,sizeof col);
    	ll ans=0;
    	fo(i,1,n){
    		if(~col[i])continue;
    		cnt[col[i]=0]=cnt[1]=cnt[2]=siz=flag=0;
    		dfs(i);
    		if(flag)ans+=(cnt[0]+cnt[1]+cnt[2])*(cnt[0]+cnt[1]+cnt[2]);
    		else if(cnt[0]&&cnt[1]&&cnt[2])ans+=cnt[0]*cnt[1]+cnt[1]*cnt[2]+cnt[2]*cnt[0];
    		else ans+=siz;
    	}
    	printf("%lld
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    ARP投毒攻击
    sniffer简单使用
    MAC泛洪攻击
    又是一题反序列化了解一下???
    关于parse_str变量覆盖分析
    超级ping(多线程版)
    文本输入框input将输入转换为统一大小写
    通俗易懂JSONP讲解
    通俗易懂JSONP讲解
    Fastjson主要接口和类库说明
  • 原文地址:https://www.cnblogs.com/JackyhhJuRuo/p/9520126.html
Copyright © 2020-2023  润新知