首页 > 其他分享 >codeforces Connected Components(寻找补图的连通块)

codeforces Connected Components(寻找补图的连通块)

时间:2023-06-02 18:34:04浏览次数:50  
标签:int there codeforces vertices 补图 Connected listed input


http://codeforces.com/contest/920/problem/E


E. Connected Components?



time limit per test



memory limit per test



input



output


n vertices and 

codeforces Connected Components(寻找补图的连通块)_连通块

 edges. Instead of giving you the edges that exist in the graph, we give you m unordered pairs (x, y) such that there is no edge between x and y, and if some pair of vertices is not listed in the input, then there is an edge between these vertices.

X such that for every two vertices from this set there exists at least one path in the graph connecting these vertices, but adding any other vertex to X


Input

n and m (1 ≤ n ≤ 200000, 

codeforces Connected Components(寻找补图的连通块)_连通块_02

).

m lines follow, each containing a pair of integers x and y (1 ≤ x, y ≤ nx ≠ y) denoting that there is no edge between x and y. Each pair is listed at most once; (x, y) and (y, x) are considered the same (so they are never listed in the same test). If some pair of vertices is not listed in the input, then there exists


Output


k

k


Example


input


5 51 23 4 3 2 4 2 2 5


output


21 4



【题意】

输入一个n点m边的无向图,求其补图的连通块。

补图:在完全图中,去掉原图中的边。

【分析】

在原图中不相接的两个点,在补图中肯定相连。因此,对一个点u而言,标记其所有的邻接边,那么没被标记的点,就是补图中u的邻接点。找到u的补图中的邻接点之后,再由找到的这些点用同样的方法找到邻接点,从而找出整个连通块。很明显BFS维护最合适。

【代码】

#include<bits/stdc++.h>
#define mset(a,i) memset(a,i,sizeof(a))
using namespace std;
const int N=202020;
struct node{
    int t,next;
}e[N<<2];
int head[N],cnt;
void add(int u,int v)
{
    e[cnt]=node{v,head[u]};
    head[u]=cnt++;
}
bool vis[N],vi[N];
int d[N];
int ans[N];
int main()
{
    int n,m,u,v;
    while(cin>>n>>m)
    {
        mset(head,-1);cnt=0;
        while(m--)
        {
            scanf("%d%d",&u,&v);
            add(u,v);
            add(v,u);
        }
        for(int i=1;i<=n;i++)d[i]=i;
        int dtop=n,top=0;

        mset(vis,0); //标记已完成的点
        mset(vi,0);  //标记相邻点
        queue<int>q;
        for(int j=1;j<=n;j++)if(!vis[j])
        {
            ans[top++]=0; //新连通块,bfs找到此连通块所有点
            q.push(j);
            while(!q.empty())
            {
                int u=q.front();q.pop();
                vis[u]=1;
                ans[top-1]++;
                for(int i=head[u];~i;i=e[i].next) //当前图的邻接点
                    if(!vis[e[i].t])
                        vi[e[i].t]=1;
                for(int i=1;i<=dtop;)
                {
                    if(!vis[d[i]]&&!vi[d[i]]) //反图的相邻点
                    {
                        q.push(d[i]);
                        d[i]=d[dtop--]; //删除点d[i](优化)
                    }
                    else vi[d[i++]]=0;
                }
            }
        }
        sort(ans,ans+top);
        printf("%d\n",top);
        for(int i=0;i<top;i++)
            printf("%d%c",ans[i],i<top-1?' ':'\n');
    }
}


标签:int,there,codeforces,vertices,补图,Connected,listed,input
From: https://blog.51cto.com/u_16125110/6404550

相关文章

  • Codeforces 1515I - Phoenix and Diamonds(值域倍增+线段树)
    首先\(c\)很大,因此复杂度跟\(c\)有关的项肯定只能是\(\logc\)之类的。类比IOI2021dungeons的套路,我们对值域进行分层,假设\(c\in[2^{\omega-1},2^{\omega})\),考虑令重量在\(\ge2^{\omega-1}\)的物品为“重物品”,其他物品为“轻物品”,那么一个显然的性质是我们最多只......
  • Codeforces Beta Round #2--B题 (DP)
    题目:Theleastroundway 1000*1000的方阵,每个格子有一个非负整数,现在要从左上走到右下,每次只能向下或者向右走。目标是使得所有走的格子里的数的乘积里,末尾0的个数最少,要求输出最有解和走法。不用怎么想也知道基本是个dp了,可以发现其实只有2和5的因子是有用的,但是如果状态同时记......
  • Codeforces Round 875 (Div. 2)B-D
    原题链接:https://codeforces.com/contest/1831原文:https://www.cnblogs.com/edgrass/p/17440602.html(B)Arraymerging主体思想是找到ab数组的最长相同字串(c中操作可实现连续)1#include<bits/stdc++.h>2usingnamespacestd;3intmain(){4intt;5cin>>......
  • Codeforces Round #548 (Div. 2) 题解
    题目链接http://codeforces.com/contest/1139 A.EvenSubstrings判断个位是否是奇数即可。#include<iostream>#include<set>#include<array>#include<vector>usingnamespacestd;typedeflonglongll;constintmx=1e5+10;lldp[mx][2];charstr[......
  • CodeForces 1250E [2-sat]
    题目链接:https://codeforces.com/contest/1250/problem/E 解题思路:首先根据反转的性质有:    有字符串a,b,a的反转A,b的反转B,如果a和b匹配值为K,那么A和B的值也为K    同样a和B匹配值为M,那么A和b的匹配值也为M,因此有对称性那么就可以转换成2-sat问题了,设点i的对立......
  • Codeforces Round #594 (Div. 2) 题解
    题目链接:https://codeforces.com/contest/1248 A-IntegerPoints水题#include<bits/stdc++.h>usingnamespacestd;constintmx=1e5+5;typedeflonglongll;inta[mx],b[mx];intmain(){ intt; scanf("%d",&t); while(t--){ intn,m; scan......
  • CodeForcese 1256F [思维]
    题目链接:https://codeforces.com/problemset/problem/1256/F 解题思路:任意的翻转都可以认为是翻转若干个长度为2的,交换两个数主要奇数次翻转。两个串可以翻转成一样,那么一定可以再花费一样的翻转次数变成有序的字符串,连续两个相等的字符翻转任意数次是一样的,所以只要有两个字符......
  • Codeforces Round #599 (Div. 2) 题解
    题目链接:https://codeforces.com/contest/1243 A-MaximumSquare水题不说了#include<bits/stdc++.h>usingnamespacestd;constintmx=1e5+50;typedeflonglongll;intn;inta[mx];intmain(){ intt; scanf("%d",&t); while(t--){ scan......
  • Codeforces #564 (Div. 2) C. Nauuo and Cards[贪心]
    题目链接:http://codeforces.com/contest/1173/problem/C 解题思路:很明显总的抽卡次数是不会超过2*n的。然后我们再将情况分成两种:1.编号1的卡片已经在里面了,并且最底部已经形成了一个1~x的连续的卡片,而且之后x+1,x+2都可以来得及补上,在这种情况下抽卡次数肯定就不会超过n了。2.......
  • Codeforces #564 (Div. 2) D. Nauuo and Circle[树形DP]
    题目链接:http://codeforces.com/contest/1173/problem/D 解题思路:首先得知道按照圆周顺序的话,那么一颗子树必须存放在连续的一段区间里面,现在我们假设根节点是1,那么一颗为u做根节点的子树他的方案数就是各个儿子的方案数的乘积最后再乘以儿子个数+1(u节点本身)的排列方案数。所......