[agc011c]Squared Graph

前言

很简单的计数套路。
没看过题解我有可能做复杂了。

题意

不想讲。

做法

先讲原图孤立点统计贡献,接下来讨论的所有点均不孤立。
我们想要统计一个联通块,可以统计特征点的个数。
即对于一个x.y,如果其是特征点,不存在与其联通的一个点t.u满足 t<x 或x.z满足 z<y
容易发现特征点第一维只能是原图中其所在联通块的最小编号点。
第二维如果也是最小编号点,显然也是可以的。
还有一种情况,就是第二维点所在联通块是二分图,且其和最小编号点不属于同一个集合,那么我们无法通过变化得到一个x.z(如果不是二分图或者与最小编号点属于同一集合,显然能找到这个x.z)。
注意这样的非最小编号第二维,每个二分图联通都找一个就行,所以等价于二分联通图个数。

#include
#include
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
typedef long long ll;
const int maxn=100000+10;
int fa[maxn],co[maxn];
bool bz[maxn],pd[maxn];
int i,j,k,l,r,t,n,m,cnt;
ll ans;
int getfa(int x){
    if (!fa[x]) return x;
    int t=getfa(fa[x]);
    co[x]^=co[fa[x]];
    return fa[x]=t;
}
int main(){
    //freopen("data.in","r",stdin);
    scanf("%d%d",&n,&m);
    fo(i,1,m){
        scanf("%d%d",&j,&k);
        bz[j]=1;bz[k]=1;
        l=getfa(j);r=getfa(k);
        if (lif (l==r&&co[j]==co[k]) pd[l]=1;
        if (l==r) continue;
        pd[r]|=pd[l];
        fa[l]=r;
        co[l]=co[j]^co[k]^1;
    }
    fo(i,1,n)
        if (!bz[i]) cnt++;
    ans=(ll)cnt*(n-cnt)*2+(ll)cnt*cnt;
    cnt=0;
    fo(i,1,n)
        if (bz[i]&&!fa[i]) cnt++;
    ans+=(ll)cnt*cnt;
    cnt=0;
    /*fo(i,1,n)
        if (bz[i]&&fa[i]){
            k=getfa(i);
            if (!pd[k]&&co[i]!=co[k]) cnt++;
        }*/
    fo(i,1,n)
        if (bz[i]&&!fa[i]&&!pd[i]) cnt++;
    fo(i,1,n)
        if (bz[i]&&!fa[i]&&!pd[i]) ans+=(ll)cnt;
    printf("%lld\n",ans);
}

你可能感兴趣的:(并查集)