CodeForces - 920E Connected Components? [bfs+链表]

本文介绍了一种算法,用于解决给定原图的补图时如何计算原图的连通块个数及各连通块大小的问题。通过遍历未归纳的点并使用链表维护状态,实现O(n+m)的时间复杂度。

题意:给你原图的补图,求原图的连通块个数,与每个连通块大小。

#include<stdio.h>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
vector<int>vt[200005];
int ok[200005],mark[200005];
int sta[200005],tot;
int	last[200005],nxt[200005];
queue<int>que;
inline char nc(){  
    static char buf[100000],*p1=buf,*p2=buf;  
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;  
}  
inline int _read(){  
    char ch=nc();int sum=0;  
    while(!(ch>='0'&&ch<='9'))ch=nc();  
    while(ch>='0'&&ch<='9')sum=sum*10+ch-48,ch=nc();  
    return sum;  
}  

int main()
{
	int n,m;
	//scanf("%d%d",&n,&m);
	n=_read();
	m=_read();
	for(int i=0;i<m;i++)
	{
		int u,v;
		//scanf("%d%d",&u,&v);
		u=_read();
		v=_read();
		vt[u].push_back(v);
		vt[v].push_back(u);
	}
	for(int i=1;i<=n;i++)
		last[i]=i-1,nxt[i]=i+1;
	nxt[0]=1;last[n+1]=n;
	for(int i=1;i<=n;i++)
	{
		if(ok[i])continue;
		que.push(i);
		tot++;
		int la=last[i],nx=nxt[i];
		nxt[la]=nx;
		last[nx]=la;
		while(!que.empty())
		{
			int k=que.front();
			que.pop();
			sta[tot-1]++;
			ok[k]=1;
			for(int j=0;j<vt[k].size();j++)
				mark[vt[k][j]]=1;
			for(int j=nxt[0];j<=n;j=nxt[j])
			{
				if(mark[j])continue;
				que.push(j);
				int la=last[j],nx=nxt[j];
				nxt[la]=nx;
				last[nx]=la;
			}
			for(int j=0;j<vt[k].size();j++)
				mark[vt[k][j]]=0;
		}
	}
	sort(sta,sta+tot);
	printf("%d\n",tot);
	for(int i=0;i<tot;i++)
		printf("%d ",sta[i]);
} 

题解:将点划分为,未归纳如连通块与已经被归纳入某个连通块两种情况,for所有未归纳的点,对于当前点i遍历所有其他未归纳的点,若原图有边则将该点加入。通过链表维护未归纳的点,时间复杂度为O(n+m)。

AC代码:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值