agc011_c Squared Graph

题意描述

定义图的乘法:A×B生成一个新图C,其中任意a∈A,b∈B,都对应C图中一个新点(a,b),C图中任意两点(a,b)、(a',b')之间存在边,当且仅当A、B中存在边(a,a')、(b,b')。

给出一个图G,求G×G中有多少个连通块。

思路

这道题目好啊,一开始以为是不可做题系列……

关键就是要充分理解题意,建立形象化的问题模型。

新图上的点(a,b)和点(c,d)之间有一条边,当且仅当原图上存在边(a,c)、(b,d)。

这实际上相当于一次移动:让a和b同时移动到相邻位置,到达一个新的状态(c,d)。

因此两个状态处于同一个联通块,实质上就是要求它们能够通过上述操作互相变换。

这样问题就形象多了。

容易发现状态(a,b)能够到达状态(c,d),

当且仅当存在路径(不一定是简单路径)A=a-->c,B=b-->d,满足A和B的长度奇偶性相同。

谈到奇偶性,常用的模型是二分图。

记a所在的连通块是Ga,b所在的连通块是Gb,

(1)可以发现,如果|Ga|=1,那么Ga×Gb得到了|Gb|个独立的点(|Gb|=1同理)。

证明:显然。

(2)可以发现,如果Ga和Gb中至少有一个存在奇环(即不是二分图),那么Ga×Gb得到的任意两个状态之间都连通。

证明:对于任意两个状态(a,b)、(c,d),可以先对(a,b)进行若干次操作,使得b绕着一个奇环走任意圈数,可以发现每走一圈,a-->c和b-->d的奇偶性就变一次,而它们奇偶性一样就可以互相转化了。

(3)可以发现,如果Ga和Gb都是二分图,那么Ga×Gb得到的状态形成了两大连通块。

证明:对所有点进行黑白染色,那么根据a和b的颜色划分,只会存在这四种状态:(a=黑,b=白)、(a=黑,b=黑),(a=白,b=白)、(a=白,b=黑)。显然在二分图中,(a=黑,b=白)和(a=白,b=黑)都可以互相转化;(a=黑,b=黑)和(a=白,b=白)也都可以互相转化;而这两大阵营之间奇偶性不同,永远不可能互相转化。得证。

显然Ga×Gb和Gb×Gc不存在任何联系,Ga×Gb和Gc×Gd更不会存在任何联系,因此可以对G中任意一对连通块独立地统计,累加到答案里。具体地,记单点有unit个,二分图有even个,非二分图且点数>1的有odd个,那么答案为2*unit*n-unit*unit+2*odd*(odd+even)-odd*odd+2*even*even(这个自己算算就知道了,没什么好说的)。

#include <cstdio>
#define ll long long
#define rep(i,j,k) for (i=j;i<=k;i++)
using namespace std;
const int N=1e5+5,M=2e5+5;
int n,m,u,v,i,j;
int En,flg,V,vis[N],col[N],fst[N],nxt[M*2],to[M*2];
ll ans,unit,even,odd;
void add(int u,int v) {
	En++; nxt[En]=fst[u]; fst[u]=En; to[En]=v;
}
void dfs(int x,int p)
{
	int j,v;
	V++; col[x]=p; vis[x]=1;
	for (j=fst[x];j;j=nxt[j])
	{
		v=to[j];
		if (vis[v]) {
			if (col[v]==col[x]) flg=1;
			continue;
		}
		dfs(v,p^1);
	}
}
int main()
{
	scanf("%d%d",&n,&m);
	rep(i,1,m)
	{
		scanf("%d%d",&u,&v);
		add(u,v); add(v,u);
	}
	rep(i,1,n)
	if (!vis[i])
	{
		V=0; flg=0;
		dfs(i,0);
		if (V==1) unit++;
		else if (flg) odd++;
		else even++;
	}
	ans=2*unit*n-unit*unit+2*odd*(odd+even)-odd*odd+2*even*even;
	printf("%lld\n",ans);
	return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值