P2097 资料分发

题目描述

有一些电脑,一部分电脑有双向数据线连接。如果一个电脑得到数据,它可以传送到的电脑都可以得到数据。现在,你有这个数据,问你至少将其输入几台电脑,才能使所有电脑得到数据。

输入格式

第一行两个数n,m。n是点数,m是边数。

接下来m行,每行2个整数p,q表示p到q有一条双向数据线。

输出格式

一个整数,表示至少输入的电脑数量。

输入输出样例

输入 #1
4 5
1 2
1 3
2 3
2 1
3 4
输出 #1
1

说明/提示

对于30%的数据:n<=100,m<=1000

对于60%的数据:n<=2000,m<=100000

对于100%的数据:n<=100000, m<=200000

数据不保证没有重边,不保证没有自回环

这道题目我一开始想的是用dijkstra来计算每个点到各个点的最短距离,然后把每个点距离为1的加起来就是答案,但是呢,交上去只有20分,因为这样需要开一个bool数组来确定你这个点搜没搜到,每遍历一次都要重置状态,这样状态就会乱.

这个题有两种做法,一种是并查集遍历,另一种是dfs遍历图(本质还是图论),总体来说还是很简单的,反正是学到新东西了

这个是图遍历,dfs

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=3000010;
 4 bool vis[N];
 5 int n,m,h[N],e[N],ne[N],idx,res;
 6 void add(int a,int b)
 7 {
 8     e[idx]=b,ne[idx]=h[a],h[a]=idx++;
 9 }
10 void dfs(int st)//dfs遍历图
11 {
12     vis[st]=true;
13     for(int i=h[st];i!=-1;i=ne[i])
14     {
15         int j=e[i];
16         if(!vis[j]) dfs(j);//如果这个点没被找到,就冲!
17     }
18 }
19 int main()
20 {
21     cin>>n>>m;
22     memset(h,-1,sizeof h);
23     for(int i=1;i<=m;i++)
24     {
25         int a,b;
26         cin>>a>>b;
27         add(a,b);//一定要记得双头都要建立哦
28         add(b,a);
29     }
30     for(int i=1;i<=n;i++) if(!vis[i]) dfs(i),res++;
31     cout<<res;
32     return 0;
33 }

下面是并查集

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=3000010;
 4 int p[N],n,m,res;
 5 bool vis[N];
 6 int find(int x)
 7 {
 8     if(x!=p[x])
 9         p[x]=find(p[x]);
10     return p[x];
11 }
12 int main()
13 {
14     cin>>n>>m;
15     for(int i=1;i<=n;i++) p[i]=i;
16     for(int i=1;i<=m;i++)
17     {
18         int a,b;
19         cin>>a>>b;
20         if(a!=b) p[find(a)]=find(b);
21     }
22     for(int i=1;i<=n;i++)//开始统计
23     {
24         int x=find(i);
25         if(!vis[x])
26         {
27             vis[x]=true;
28             res++;
29         }
30     }
31     cout<<res;
32     return 0;
33 }

 

posted @ 2023-05-26 15:53  o-Sakurajimamai-o  阅读(45)  评论(0)    收藏  举报
-- --