1. 程式人生 > >AGC011 C Squared Graph

AGC011 C Squared Graph

題意

定義兩個圖的乘法是:點數為它們的乘積,新圖中(x,y)到(z,w)有邊,當且僅當第一個圖(x,z)有邊,第二個圖(y,w)有邊 給出一個無向圖G,求它的平方的連通分量個數

題解

我們考慮相對一般點的情形:圖A乘上圖B 首先考慮那些孤點(即度數為0),設AB孤點個數為I 由於孤點不和任何點有連線,所以在新圖中,它所對應的那一行(列)就肯定是獨立的 也就是說,跟孤點有關的就是IAIB+IA(NBIB)+IB(NAIA)I_AI_B+I_A(N_B-I_B)+I_B(N_A-I_A) 在原圖中的一個二分圖,我們只能黑->白->黑地走,所以在對應的乘積上會有兩個連通塊 而非二分圖則可以保證最後形成的是一個連通塊 而二分圖乘上非二分圖,也是一個連通塊 綜上,答案就是 (P為非二分圖數量,Q為二分圖數量) a

ns=IAIB+IA(NBIB)+IB(NAIA)+PAPB+PAQB+QAPB+2QAQBans=I_AI_B+I_A(N_B-I_B)+I_B(N_A-I_A)+P_AP_B+P_AQ_B+Q_AP_B+2Q_AQ_B

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const
int N=1000000+5; typedef long long ll; struct node{ int u,v,nxt; }edge[N*2]; int head[N],mcnt; int du[N]; void add_edge(int u,int v){ mcnt++; edge[mcnt].u=u; edge[mcnt].v=v; edge[mcnt].nxt=head[u]; head[u]=mcnt; du[u]++; } ll I,P,Q; bool tag[N]; bool vis[N]; bool flag; void dfs
(int u){ vis[u]=1; for(int i=head[u];i;i=edge[i].nxt){ int v=edge[i].v; if(!vis[v]){ tag[v]=tag[u]^1; dfs(v); } else if(tag[u]==tag[v]) flag=false; } } int main() { int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ int u,v; scanf("%d%d",&u,&v); add_edge(u,v); add_edge(v,u); } for(int i=1;i<=n;i++){ if(vis[i]) continue; if(du[i]==0){ I++; continue; } flag=true; dfs(i); if(flag) Q++; else P++; } ll ans=1ll*2*I*n-1ll*I*I+1ll*P*P+2ll*P*Q+2ll*Q*Q; printf("%lld\n",ans); }