题意
你有一个N×Ni的网格,一开始有M个格子是黑色的。如果格子(x,y)和(y,z)都是黑色的,那你可以把(z,x)(z,x)也给涂黑,问最多能有多少个黑格子。
题解
题目描述相当于有毒,搞得跟神犇才能做的题一样。
问题转化一下:你有一个NN个点的有向图,一开始连了M条边,假如存在边(x,y)和(y,z)(y,z),那么你可以连边(z,x) 这样就可做多了。至少可以用类SPFA的方法乱搞骗分了。
我们考虑对原图进行三染色。假设某一个点是红,他连向的所有点就是蓝;蓝连向的所有点都是绿;绿连向的所有点又是红。
假如我们对某个联通块染色失败(比如一个四元环),那么不难发现,这个联通块会被操作成一个完全图,那么这种染色失败的联通块对答案的贡献就是n\times nn×n(n表示联通块内点的数量)
假如染色成功,但是只存在一种或两种颜色,那么不难发现,这个联通块分成了两层,并且只存在上层指向下层的边。这种情况下根本无法进行操作,所以对答案的贡献就是联通块的初始边数
假如染色成功,并且三种颜色都存在,那么在若干次操作之后,任意一个红点都会有直接连向所有蓝点的出边,类似的,蓝连向绿,绿连向红。所以这种情况对答案的贡献就是cnt_r\times cnt_b+cnt_b\times cnt_g+cnt_g\times cnt_rcnt r ×cnt b +cnt b ×cnt g +cnt g ×cnt r ,其中cnt_xcnt x 表示颜色为xx的点在联通块里有多少个,r,g,b就是字面意思(假设你有小学英语水平)
就这样直接做就行了,代码实现非常简单,ans记得要开long long。
AC代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cctype>
using namespace std;
inline int read(){
int re = 0,ch = getchar();
while(!isdigit(ch))ch = getchar();
while(isdigit(ch))re = (re<<1)+(re<<3)+ch-'0',ch = getchar();
return re;
}
const int maxn = 200010;
struct edge{
int v,w,nxt;
}e[maxn];
int h[maxn],cnt;
inline void add(int u,int v,int w){
e[++cnt].v = v;
e[cnt].w = w;
e[cnt].nxt = h[u];
h[u] = cnt;
}
inline int color(int c){
if(c >= 3)c -= 3;
if(c < 0)c += 3;
return c;
}
int col[maxn],cnum[3],nsz,esz;
bool flag = 1,vis[maxn];
void coloring(int u){
cnum[col[u]]++;nsz++;vis[u] = 1;
for(int i = h[u];i;i = e[i].nxt){
int v = e[i].v;
if(e[i].w == 1)esz++;
if(!vis[v]) col[v] = color(col[u] + e[i].w),coloring(v);
else if(col[v] != color(col[u] + e[i].w)) flag = 0;
}
}
int n,m;
long long ans;
int main(){
n = read(),m = read();
int u,v;
for(int i = 1;i <= m;i++){
u = read(),v = read();
add(u,v,1);
add(v,u,-1);
}
for(int i = 1;i <= n;i++){
if(vis[i])continue;
memset(cnum,0,sizeof(cnum));
nsz = 0,esz = 0,flag = 1;
coloring(i);
if(!flag) ans += (long long)nsz * nsz;
else if(cnum[0] && cnum[1] && cnum[2])
ans += (long long)cnum[0] * cnum[1]
+ (long long)cnum[1] * cnum[2] + (long long)cnum[2] * cnum[0];
else ans += esz;
}
printf("%lld",ans);
return 0;
}
本文详细介绍了洛谷AT2167题目的题意、题解和通过代码。题目涉及图论,初始有M个黑格子,通过特定条件可以增加黑格子数量,转化为有向图的染色问题。通过三染色法分析不同情况对答案的贡献,最终给出简单的AC代码实现。

1794

被折叠的 条评论
为什么被折叠?



