• [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);
    }
  • 相关阅读:
    浅拷贝和深拷贝问题
    指针遍历数组时用法
    一维数组和指针
    leetcode
    tmux
    git
    einsum详解
    spark快速大数据分析 读书笔记
    maven配置
    bash 学习笔记
  • 原文地址:https://www.cnblogs.com/coco-night/p/9733256.html
Copyright © 2020-2023  润新知