【agc006f】Blackout(神仙题)
【agc006f】Blackout(神仙题)
翻译
给定一个\(n*n\)的网格图,有些格子是黑色的。如果\((x,y),(y,z)\)都是黑色的,那么\((y,x)\)也会被染黑,求最终黑格子数量。
题解
网格图我们显然是存不下的,把它转化成图来考虑。于是题目变成了:给定一个\(n\)个点\(m\)条边的图,如果\(x\rightarrow y\),\(y\rightarrow z\)的边都存在,那么连边\(z\rightarrow x\),回答边的数量。
然后开始手动翻译题解。
首先,我们可以计算每一个弱联通块(把边看成无向边的联通块),那么答案显然就是所有弱联通块的答案的总和。我们先假定图是一个弱联通图。
考虑这样一种情况,我们把点依次标号,然后在\(i\)和\(i+1\)之间连边,那么如果\(s\)和\(t\)之间存在边\(s\rightarrow t\),那么当且仅当\(t\equiv s+1(mod\ 3)\)。具有一定启发意义,我们考虑在模\(3\)的意义下搞点事情。我们用\(A,B,C\)给所有点做标记,并且强制要求对于任意一条边,只可能是\(A\rightarrow B\),\(B\rightarrow C\),\(C\rightarrow A\)。这样标号的方式可能不存在,但是不难证明一旦存在合法的标号方案,那么标号的方法唯一(不考虑循环\(ABC\)的顺序)。你可以把整个图给\(dfs\)一遍,这样子可以得到唯一的染色方案,或者证明它不存在。
通过标号的结果,我们可以得到三种情况,给出每种情况下的结论,等下再给出证明。
- 当标号存在,但是并没有用到所有的三种颜色,那么你无法在这个联通块中进行任何操作。
- 当标号存在,并且所有的三种颜色都被用到,那么你可以把所有\(AB\)之间连边,\(BC\)之间连边,\(CA\)之间连边,并且只能连这些边。
- 当标号方案不存在,你可以给任意一对点之间连边,包括自环。
利用结论,可以很容易的计算出答案,时间复杂度\(O(m)\)。代码如下,证明内容(当然是翻译的啊)在代码后面。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
#define ll long long
#define MAX 100100
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
struct Line{int v,next,w;}e[MAX<<1];
int h[MAX],cnt=1,dg[MAX];
inline void Add(int u,int v,int w){e[cnt]=(Line){v,h[u],w};h[u]=cnt++;}
int n,m;ll ans;
int vis[MAX],f[3],edge,size;bool label;
void dfs(int u,int d)
{
vis[u]=d;f[d]+=1;++size;
for(int i=h[u];i;i=e[i].next)
{
int v=e[i].v;if(e[i].w==1)++edge;
if(vis[v]==-1)dfs(v,(d+e[i].w)%3);
else if(vis[v]!=(vis[u]+e[i].w)%3)label=false;
}
}
int main()
{
n=read();m=read();
for(int i=1;i<=m;++i)
{
int x=read(),y=read();
Add(x,y,1);Add(y,x,2);
}
memset(vis,-1,sizeof(vis));
for(int i=1;i<=n;++i)
if(vis[i]==-1)
{
label=true;f[0]=f[1]=f[2]=0;size=edge=0;dfs(i,0);
if(label)ans+=(!min(f[0],min(f[1],f[2])))?(edge):(1ll*f[0]*f[1]+1ll*f[1]*f[2]+1ll*f[2]*f[0]);
else ans+=1ll*size*size;
}
cout<<ans<<endl;
return 0;
}
当标号存在,但是并没有用到所有的三种颜色,那么你无法在这个联通块中进行任何操作。
如果存在边\((x,y)\)和\((y,z)\),那么必定意为这所有的三种颜色都会被用到。既然如此,那么意味着这里不存在上述的边,所以你不能连出任何一条新边。
当标号存在,并且所有的三种颜色都被用到,那么你可以把所有\(AB\)之间连边,\(BC\)之间连边,\(CA\)之间连边,并且只能连这些边。
必定存在若干形如\((x,y),(y,z)\)这样的边,我们不妨令\(x\)染\(A\),\(y\)染\(B\),\(z\)染\(C\)。我们可以看出所有新连的边加上原边会构成一个个三角形。举个例子,令\(v\)存在一条边\((v,x)\),那么必定存在边\((y,v)\),那么我们不难证明任意一个\(v\)一定和\(x,y,z\)三个点中的两个有直接的边相连。所以任意的\(A\)都会连出一条\(A\rightarrow B\),其他的边同理。
当标号方案不存在,你可以给任意一对点之间连边,包括自环。
我们证明至少会存在一个自环。既然标号方案不存在,那么必定存在一个环导致了矛盾,注意,这个环不一定是有向环。那么这个环至少存在两条边\((x,y)\),\((y,z)\),那么我们可以连上\((z,x)\),那么等价于我们看这个环的时候可以直接跳过\(y\)。既然原先的环会导出矛盾,那么当前这个环照样会导出矛盾,那么我们重复这个过程,就可以得到自环。而其他的边存在的原因和前面两个证明类似,不再重复证明。
【agc006f】Blackout(神仙题)的更多相关文章
- [agc006f] Blackout 神题
Description 给你一个NN行NN列的网格,第ii行第jj列的格子用(i,j)(i,j)表示 一开始的时候有MM个格子被涂成黑色,其他的格子都是白色,具体一点,涂成黑色的格子为(a1,b1 ...
- 2017国家集训队作业[agc006f]Blackout
2017国家集训队作业[agc006f]Blackout 题意: 有一个\(N*N\)的网格,一开始有\(M\)个格子被涂黑,给出这\(M\)个格子,和染色操作:如果有坐标为\((x,y),(y,z) ...
- Codeforces & Atcoder神仙题做题记录
鉴于Codeforces和atcoder上有很多神题,即使发呆了一整节数学课也是肝不出来,所以就记录一下. AGC033B LRUD Game 只要横坐标或者纵坐标超出范围就可以,所以我们只用看其中一 ...
- 【BZOJ5285】[HNOI2018]寻宝游戏(神仙题)
[BZOJ5285][HNOI2018]寻宝游戏(神仙题) 题面 BZOJ 洛谷 题解 既然是二进制按位的运算,显然按位考虑. 发现这样一个关系,如果是\(or\)的话,只要\(or\ 1\),那么无 ...
- 【BZOJ5213】[ZJOI2018]迷宫(神仙题)
[BZOJ5213][ZJOI2018]迷宫(神仙题) 题面 BZOJ 洛谷 题解 首先可以很容易的得到一个\(K\)个点的答案. 构建\(K\)个点分别表示\(mod\ K\)的余数.那么点\(i\ ...
- 【BZOJ1071】[SCOI2007]组队(神仙题)
[BZOJ1071][SCOI2007]组队(神仙题) 题面 BZOJ 洛谷 题解 首先把式子整理一下,也就是\(A*h+B*v\le C+A*minH+B*minV\) 我们正常能够想到的做法是钦定 ...
- 【BZOJ3244】【NOI2013】树的计数(神仙题)
[BZOJ3244][NOI2013]树的计数(神仙题) 题面 BZOJ 这题有点假,\(bzoj\)上如果要交的话请输出\(ans-0.001,ans,ans+0.001\) 题解 数的形态和编号没 ...
- 【bzoj2118&洛谷P2371】墨墨的等式(最短路神仙题)
题目传送门:bzoj2118 洛谷P2371 这道题看了题解后才会的..果然是国家集训队的神仙题,思维独特. 首先若方程$ \sum_{i=1}^{n}a_ix_i=k $有非负整数解,那么显然对于每 ...
- P3202 [HNOI2009]通往城堡之路 神仙题
这个题不是坑人吗...写个tarjan标签,然后拿这么个神仙题来搞...代码有点看不懂,有兴趣的可以去洛谷题解区看看,懒得想了. 题干: 题目描述 听说公主被关押在城堡里,彭大侠下定决心:不管一路上有 ...
随机推荐
- C#例题集
收集一些从网上看到的例题 1.抽象类 抽象类不能被实例化一个抽象类只能通过接口和作为其它类的基类使用 抽象方法的声明只能在抽象类中 抽象方法必定不能实现(方法带一对{}都不行) 当一个子类集成自抽象类 ...
- Python3的深拷贝和浅拷贝
a = 1 b = a a = 2 print(a, b) print(id(a), id(b)) """ 运行结果 2 1 1445293568 1445293536 ...
- django-simple_tag、filter
simple_tag与filter的用法 1.支持自定义函数处理方法 2.支持模板调用 创建步骤: a.在app目录下创建templatetags文件夹 b.在templatetags中创建任意名称. ...
- 基于Python的信用评分卡模型分析(二)
上一篇文章基于Python的信用评分卡模型分析(一)已经介绍了信用评分卡模型的数据预处理.探索性数据分析.变量分箱和变量选择等.接下来我们将继续讨论信用评分卡的模型实现和分析,信用评分的方法和自动评分 ...
- Golang 2018.1.2激活及使用技巧
对于做Java开发的同学使用最熟练的开发工具应该当属Eclipse了吧,但是做到后面的话一般都会转用Intellij Idea.至于转用Intellij有什么好处我就不赘述了,简言之就是功能强大,使用 ...
- 20172324《Java程序设计》第3周学习总结
20172324<Java程序设计>第3周学习总结 教材学习内容总结 随机数,记住要返回的是指定的字符前一个. String类型的一些用法,例如concat(连接),toUpperCase ...
- java BufferedWriter写数据不完全
package com.brucekun.keyword; import java.io.BufferedReader; import java.io.BufferedWriter; import j ...
- 四则运算(window窗体程序)
我的第一个程序 忙活了半个下午做出来了,勉强可以见人,虽然还有些瑕疵,但是我也尽力了...... 我做的是一个能对0--10之间的整数进行四则运算的,题目的数据是程序自动生成的,而且程能接收用户输入的 ...
- java equals()方法的注意事项
1.在写代码的时候,我们有时候需要判断两个相同类的对象的值是否全部相等,很多人想到的就是equals()方法,但是equals方法真的是可以比较吗?其实equals方法比较的并不是两个对象的值,它只是 ...
- [图的遍历&多标准] 1087. All Roads Lead to Rome (30)
1087. All Roads Lead to Rome (30) Indeed there are many different tourist routes from our city to Ro ...