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 }

浙公网安备 33010602011771号