AtCoder Grand Contest 006 F - Blackout

Description

在 \(n*n\) 的棋盘上给出 \(m\) 个黑点,若 \((x,y)\),\((y,z)\) 都是黑点,那么 \((z,x)\) 也会变成黑点,求最后黑点的数量
题面

Solution

把点 \((x,y)\) 看作一条从 \(x\) 到 \(y\) 的有向边
我们分析性质:
如果存在一个自环,那么这个点所在的连通块就会变成一个完全图
原因是和这个点有单向边的点都会变成双向边,有双向边之后就会形成自环,那么就可以一直重复这个过程,就变成了完全图

我们想办法判断图中有没有自环,我们发现:对原图进行三染色之后:
1.如果产生了矛盾,那么就有自环,就会形成一个完全图,这个连通块的答案就是点数的平方
2.如果染色完成了,那么算出产生的边的个数和原图边的个数就行了

对于第二种情况,还需要一些性质:
首先如果 \(color[x]±1 \mod 3 =color[u]\) 且 \(x,u\) 在同一连通块内,则一定有边存在
所以设 \(a[x]\) 表示颜色为 \(x\) 的点的数量,答案就是 \(a[1]*a[2]+a[2]*a[3]+a[1]*a[3]\)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
int n,m,head[N],nxt[N*2],to[N*2],num=0,c[N],E=0,a[4],dis[N*2];
bool flag=0,vis[N*2];
vector<int>S;
inline void link(int x,int y,int z){
    nxt[++num]=head[x];to[num]=y;head[x]=num;dis[num]=z;}
inline void dfs(int x){
    S.push_back(x);
    for(int i=head[x];i;i=nxt[i]){
        int u=to[i],t=c[x]+dis[i];
        if(!vis[i])vis[i]=1,E++;
        if(!t)t=3;if(t==4)t=1;
        if(c[u]){
            if(c[u]!=t)flag=1;
        }
        else c[u]=t,dfs(u);
    }
}
int main(){
    freopen("pp.in","r",stdin);
    freopen("pp.out","w",stdout);
    int x,y;ll ans=0;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        scanf("%d%d",&x,&y);
        link(x,y,1);link(y,x,-1);
    }
    for(int i=1;i<=n;i++){
        if(!c[i]){
            vector<int>().swap(S);c[i]=1;flag=0;E=0;
            dfs(i);
            memset(a,0,sizeof(a));
            for(int j=S.size()-1;j>=0;j--)a[c[S[j]]]++;
            if(flag)ans+=(ll)S.size()*S.size();
            else if(!a[1] || !a[2] || !a[3])ans+=E/2;
            else ans+=1ll*a[1]*a[2]+1ll*a[2]*a[3]+1ll*a[1]*a[3];
        }
    }
    cout<<ans<<endl;
    return 0;
}

原文地址:https://www.cnblogs.com/Yuzao/p/8678151.html

时间: 2024-07-30 15:37:05

AtCoder Grand Contest 006 F - Blackout的相关文章

AtCoder Grand Contest 067 F - Yakiniku Restaurants

题目传送门:https://arc067.contest.atcoder.jp/tasks/arc067_d 题目大意: 有\(N\)家烧烤店,在直线上按顺序排列,第\(i\)家烧烤店和第\(i+1\)家烧烤店的距离为\(A_i\).你有\(M\)张烧烤券,在第\(i\)家烧烤店使用第\(j\)张券可以获得\(B_{i,j}\)的快乐,你可以在某家烧烤店使用多张券.你现在可以从某个烧烤店开始,使用所有的券,使得你的快乐值减去所走路程最大 我们考虑每个\(B_{i,j}\)的贡献,我们找到第一个一

AtCoder Grand Contest 006 题解

传送门 \(A\) 咕咕 const int N=105; char s[N],t[N];int n; inline bool eq(R int k){fp(i,1,k)if(s[n-k+i]!=t[i])return false;return true;} int main(){ scanf("%d%s%s",&n,s+1,t+1); fd(k,n,0)if(eq(k))return printf("%d\n",(n<<1)-k),0; ret

AtCoder Grand Contest 025 Problem D

www.cnblogs.com/shaokele/ AtCoder Grand Contest 025 Problem D Time Limit: 2 Sec Memory Limit: 1024 MB Description Takahashi is doing a research on sets of points in a plane. Takahashi thinks a set \(S\) of points in a coordinate plane is a good set w

AtCoder Grand Contest 024 Problem E(动态规划)

www.cnblogs.com/shaokele/ AtCoder Grand Contest 024 Problem E Time Limit: 2 Sec Memory Limit: 1024 MB Description Find the number of the possible tuples of sequences (\(A_0,A_1,-,A_N\)) that satisfy all of the following conditions, modulo \(M\): ? Fo

AtCoder Grand Contest 011

AtCoder Grand Contest 011 upd:这篇咕了好久,前面几题是三周以前写的... AtCoder Grand Contest 011 A - Airport Bus 翻译 有\(n\)个乘客到达了飞机场,现在他们都要坐车离开机场.第\(i\)个乘客到达的时间是\(T_i\),一个乘客必须在\([T_i,T_i+k]\)时刻做到车,否则他会生气.一辆车最多可以坐\(C\)个人.问最少安排几辆车可以让所有人都不生气. 题解 从前往后贪心即可. #include<iostream

AtCoder Grand Contest 014

AtCoder Grand Contest 014 A - Cookie Exchanges 有三个人,分别有\(A,B,C\)块饼干,每次每个人都会把自己的饼干分成相等的两份然后给其他两个人.当其中有一个人的饼干数量是奇数的时候停止,求会进行几次这样子的操作,或者会永远进行下去. 首先无解的情况一定是三个数都是相等的偶数. 否则直接暴力模拟就行了.(盲猜答案不会很大) 证明一下答案的范围:不妨令\(A\le B\le C\),那么最大值和最小值之间的差就是\(C-A\),那么执行完一次操作之后

AtCoder Grand Contest 016

AtCoder Grand Contest 016 A - Shrinking 你可以进行一个串的变换,把一个长度为\(n\)的串\(S\)可以变成长度为\(n-1\)的串\(T\),其中\(T_i\)要么是\(S_i\)要么是\(S_{i+1}\). 现在问你最少进行多少次这个操作,能够使最终得到的\(T\)只由一个字符构成. \(|S|\le 100\) 首先枚举最终字符是哪一个.那么首先在\(S\)末尾加上一个这个字符,那么这个最小步数等于对于所有位置而言,离它最近的枚举的字符到这个位置的

Atcoder Grand Contest 018 E - Sightseeing Plan

Atcoder Grand Contest 018 E - Sightseeing Plan 枚举从第二个矩形的 \((x_1,y_1)\) 进入,\((x_2,y_2)\) 出来,那么中间可以选的点的数量是 \(x_2+y_2-x_1-x_2+1\) ,也就是说对于每一条合法路线,从 \((x_1,y_1)\) 进入的贡献为 \(-x_1-x_2\) ,从 \((x_2,y_2)\) 出来的贡献为 \(x_2+y_2+1\) ,枚举一下第二个矩形边界上的点,我们只需要分别计算某个点到第一个矩形

【Atcoder Grand Contest 020 E】 Encoding Subsets

Atcoder Grand Contest 020 E 题意:给一个\(0-1\)字符串,如果其中有一段重复,就可以表示成\((\)这一块的表示\(\times\)出现次数\()\). 问这个字符串的所有子集中有多少种表示方法. 思路:考虑\(dp(s)\)表示字符串\(s\)的答案. 那么我们得考虑第一个表示成的位置是什么. ①第一位就是表示的第一位,不参与循环.那么转移到\(dp(s.substr(1))\),并且如果这位是\(1\),那么乘上\(2\),因为这位可能是\(0\). ②一个前