小花梨判连通(DFS或BFS或并查集+vector+map)——“美登杯”上海市高校大学生程序设计邀请赛 (华东理工大学)

(https://acm.ecnu.edu.cn/contest/173/problem/C/)
在这里插入图片描述

题目大意:

小花梨给出?个点,让?位同学对这?个点任意添加无向边,构成?张图。小花梨想知道对于每个点?,存在多少个点?(包括?本身),使得?和?在这?张图中都是连通的。

题解:

  • 直接DFS、BFS或者并查集对每张图进行连通块染色, 两个点在k张图中都相邻说明这两个点在k张图的染色 都是一样的
  • map<vector< int >,int>存下每个点在k张图的颜色序列出现的次数即可。

DFS(深搜):

/*AC 1.008*/
#include<iostream>
#include<vector>
#include<map>
const int MAX=1e5+10;
using namespace std;
int nowcolor,n,k;
bool book[MAX];
vector<int>G[MAX];
vector<int>color[MAX];
map<vector<int>,int>Map;
void dfs(int i)
{
    book[i]=1;color[i].push_back(nowcolor);
    for(int j=0;j<G[i].size();j++)
        if(!book[G[i][j]])dfs(G[i][j]);
}
int main()
{
    ios::sync_with_stdio(false);cin.tie(0);
    cin>>n>>k;
    while(k--)
    {
        for(int w=1;w<=n;w++)G[w].clear(),book[w]=0;
        int a,u,v;
        cin>>a;
        for(int i=1;i<=a;i++)
            cin>>u>>v,
            G[u].push_back(v),
            G[v].push_back(u);

    nowcolor=0;
    for(int i=1;i<=n;i++)
        if(!book[i])nowcolor++,dfs(i);
    }

    for(int i=1;i<=n;i++)
        Map[color[i]]++;
    for(int i=1;i<=n;i++)
        cout<<Map[color[i]]<<endl;
    return 0;
}

BFS(广搜):

/*AC 0.739*/
#include<bits/stdc++.h>
#define _ ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
using namespace std;
const int MAX=1e5+10;
vector<int>G[MAX];
vector<int>color[MAX];
int que[MAX];
map<vector<int>,int>Map;
bool book[MAX];
int main()
{_
    int n,k;
    cin>>n>>k;
    while(k--)
    {
        for(int i=1;i<=n;i++)
            G[i].clear(),book[i]=0;
        int a,u,v,nowcolor;
        cin>>a;
        for(int i=1;i<=a;i++)
            cin>>u>>v,G[u].push_back(v),G[v].push_back(u);

        nowcolor=0;
        for(int i=1;i<=n;i++){
            if(!book[i]){
                nowcolor++;
                int head=1,tail=1;
                que[tail++]=i;
                book[i]=1;
                color[i].push_back(nowcolor);
                while(head<tail/*&&tail<=n*/)
                {
                    int t=que[head];
                    for(int j=0;j<G[t].size();j++){
                        if(!book[G[t][j]]){
                            que[tail++]=G[t][j];
                            book[G[t][j]]=1;
                            color[G[t][j]].push_back(nowcolor);
                        }
                        //if(tail>n)break;
                    }
                    head++;
                }
            }
        }
    }
    for(int i=1;i<=n;i++)
        Map[color[i]]++;
    for(int i=1;i<=n;i++)
        cout<<Map[color[i]]<<endl;

    return 0;
}

并查集:

/*AC 0.345*//*(以下代码借鉴自其他博客)*/
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<map>
#include<vector>
using namespace std;
typedef long long ll;
const int N=1e5+20;
vector<int>zu[N];
map<vector<int>,int>mp;
int pre[N],num[N];
int find(int x)//并查集的查操作 
{
	if(pre[x]==x)
		return x;
	return pre[x]=find(pre[x]);
}
void merge(int x,int y)//并查集的并操作 
{
	int fx=find(x);
	int fy=find(y);
	if(fx!=fy)
	{
		if(num[fx]>num[fy])
		{
			pre[fy]=fx;
			num[fx]+=num[fy];
		}
		else
		{
			pre[fx]=fy;
			num[fy]+=num[fx];
		}
	}
	return;
}
int main()
{
	int n,k;
	scanf("%d%d",&n,&k);
	for(int z=0;z<k;z++)//依次处理k张图,正在处理的图记为第z张图 
	{
		for(int i=1;i<=n;i++)//并查集初始化 
		{
			pre[i]=i;
			num[i]=1;
		}
		int m,x,y;
		scanf("%d",&m);
		for(int i=0;i<m;i++)//m个边 
		{
			scanf("%d%d",&x,&y);
			merge(x,y);
		}
		for(int i=1;i<=n;i++)//将每个点的第z个祖先push_back到zu[i]的vector中 
			zu[i].push_back(find(i));
	}
	for(int i=1;i<=n;i++)//用map统计完全相同的zu[i]的个数 
		mp[zu[i]]++;
	for(int i=1;i<=n;i++)//输出完全相同的zu[i]的个数,即和点i在k张图中都全连通的点的数量 
		printf("%d\n",mp[zu[i]]);
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值