[agc011C]Squared Graph-[二分图]
Description
Solution
我们以下考虑的情况都是原图中非孤立的点。
题目要求新图的连通块个数。这个不好算,我们考虑计算新图的联通块内的特征点(x,y),即无法通过移动找到(t,c)使得t<x,也无法找到点(x,a)满足a<y。(就是字典序最小吧)可知每个新图连通块内,都有且只会有1个特征点。这两者就等价。
对于新图的点(x,y),假如x,y所在原图连通块已确定,则第一纬度的x一定要是其所在原图联通块的最小编号点。第二维度y的话,如果y所在原图连通块是二分图,则y在被二分出来的两个点集中分别选择最小的点,都是满足要求的。(否则的话,第二维度y只能选其所在连通块内的最小编号点)
直接统计即可。(孤立点的计数。。em这个就比较好推,我就不赘述啦)
Code
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> using namespace std; typedef long long ll; const int M=2e5+10,N=1e5+10; int n,m,x,y; struct pas{int y,nxt; }g[M<<1];int h[N],tot; bool vis[N];int f[N]; int t1,t2,t3; void cover(int x) { vis[x]=1; for (int i=h[x];i;i=g[i].nxt) if (!vis[g[i].y]) cover(g[i].y); } bool dfs(int x) { vis[x]=1; bool ret=1; int i; for (i=h[x];i;i=g[i].nxt) if (!vis[g[i].y]){ f[g[i].y]=f[x]^1;if (!dfs(g[i].y)) {ret=0;break;}} else if (f[g[i].y]==f[x]) {ret=0;break;} for (;i;i=g[i].nxt) cover(g[i].y); return ret; } int main() { scanf("%d%d",&n,&m); for (int i=1;i<=m;i++) { scanf("%d%d",&x,&y); g[++tot]=pas{y,h[x]};h[x]=tot; g[++tot]=pas{x,h[y]};h[y]=tot; } for (int i=1;i<=n;i++) { if (!h[i]) t1++; else if (!vis[i]) if (dfs(i)) t2++;else t3++; } ll ans; ans=1ll*t1*t1+2ll*t1*(n-t1)+2ll*t2*t2+2ll*t2*t3+1ll*t3*t3; printf("%lld",ans); }