AGC011C Squared Graph

传送门

题意:
按如下方式定义两个无向图的乘法:
对于两个图A和B相乘,设新的无向图为C。在图A中选择任意点a,在图B中选择任意点b,对于每一对这样的点,于图C中生成新的点,这个新点的标号为(a,b)。显然,图C中共有EA*EB个点。
在图 C 中,点(a,b)与点(a’,b’)之间有边当且仅当原图中有边(a,a’)和(b,b’)
存在。
现在,给定你图A,请问A的平方(即图A乘图A)中有多少个联通分量?

题解:
考场上日常找不到规律系列
把题目简化一下,假设A、B都连通。
那么若|A|=1,则答案为|B|。如果|B|=1,同理。
若A、B都是二分图,经过找规律可以发现答案为2.
举个栗子:
AGC011C Squared Graph_第1张图片

若其中至少一个不是二分图,还是找规律,发现答案为1.
再举个栗子:
AGC011C Squared Graph_第2张图片
我太菜了,看了题解都没搞清楚证明
所以令i为孤立的点的个数,p为不是二分图的连通块的个数,q为是二分图的连通块的个数,答案就是:
         i A i B + i A ( n − i B ) + i B ( n − i A ) + p A q B + p B q A + p A p B + 2 q A q B \thickspace\thickspace\thickspace\thickspace i_Ai_B+i_A(n-i_B)+i_B(n-i_A)+p_Aq_B+p_Bq_A+p_Ap_B+2q_Aq_B iAiB+iA(niB)+iB(niA)+pAqB+pBqA+pApB+2qAqB
= i 2 + 2 ∗ i ( n − i ) + 2 p q + p 2 + 2 q 2 =i^2+2*i(n-i)+2pq+p^2+2q^2 =i2+2i(ni)+2pq+p2+2q2

代码:

#include
#define maxn 100005
#define maxm 200005
int n,m,ia,pa,qa;
bool f,val[maxn],vis[maxn];
struct node { int v; node *nxt; } edge[maxm*2],*head[maxn],*ncnt;
void addedge(int u,int v)
{
	ncnt++;
	ncnt->v=v,ncnt->nxt=head[u];
	head[u]=ncnt;
}
void dfs(int u)
{
	vis[u]=true;
	for(node *p=head[u];p;p=p->nxt)
	{
		int v=p->v;
		if(!vis[v]) { val[v]=val[u]^1; dfs(v); }
		else if(val[u]==val[v]) f=true;
	}
}
int main()
{
	ncnt=&edge[0];
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++) 
	{
		int u,v;
		scanf("%d%d",&u,&v);
		addedge(u,v); addedge(v,u);
	}
	for(int i=1;i<=n;i++)
	{
		if(!head[i]) ia++;
		else if(!vis[i])
		{
			f=false;
			dfs(i);
			if(f) pa++;
			else qa++;
		}
	}
	printf("%lld\n",1ll*ia*ia+2ll*ia*(n-ia)+1ll*pa*pa+2ll*qa*qa+2ll*pa*qa);
}

你可能感兴趣的:(懵逼了半天终于AC,图论)