This article is reproduced from: http://www.javaxxz.com/thread-359245-1-1.html
The teacher didn't talk about this thing in class, but it sounded very high. When I saw the topic and said to use it and found it, ψ(..) What! ? And check the set? What the hell? Forget it, let go of this question and brush up on something else. Today I researched and checked the collection, and found that it is quite simple. I will organize it on the blog, and I forgot to take a look at it later _(¦3"∠)_
and check
The union check set is mainly used to detect whether two points are connected. There are two main functions, one is find and the other is join. As for when to use union search, I think you think you need to judge whether these two points are connected. For example, if there are several roads between several cities, judge whether two cities are connected.
①Initialization of the union search set
The union search set is generally stored in a one-dimensional array, where pre[i]=i indicates that it is connected to itself, that is to say, no path has been added between the points.
② and check the set join
Join is mainly used to add a path to the one-dimensional array that stores and searches the set. First, determine whether the two points are connected. If they are connected, there is no need to add a path. If they are not connected, connect the root nodes of the two points together. .
void join(int x,int y){ int i,j; i = find(x); //find the root node of x j = find(y); //find the root node of y if(i!=j) //If the two root nodes are different, that is, they are not connected, connect the root nodes together pre[i] = j; //i.e. i link j }
③ And check the set find
find mainly has two parts, one is to find the root node, and the other is to compress the path.
int find(int x){ int i = x; while(pre[i]!=i) //查找根节点 i = pre[i]; //路径压缩 int j = x; int k; while(j!=i) { k = pre[j]; pre[j] = i; j = k; } return i;}
There are two examples below to explain in detail the usage of concatenating sets
Risk measurement of previous exam questions of the Blue Bridge Cup
The defense system of galaxy X consists of n space stations. There are m communication links between the n space stations, forming a communication network.
There may be direct communication between the two space stations, or transit through other space stations.
For two sites x and y (x != y), if a site z can be found such that
when z is destroyed, x and y cannot communicate, then z is called a key site about x, y.
Obviously, for a given two sites, the greater the number of keypoints about them, the greater the communication risk.
Your task is: Knowing the network structure, find the communication risk between two sites, that is: the number of key points between them.
The first line of the input data contains 2 integers n (2 <= n <= 1000), m (0 <= m <= 2000), which represent the number of stations and the number of links, respectively.
Space stations are numbered from 1 to n. A communication link is represented by the station numbers at both ends of it.
The next m lines, each line with two integers u, v (1 <= u, v <= n; u != v) represent a link.
The last line, two numbers u, v, represent the two sites being asked about the risk of communication.
Output: an integer, if the two points asked are not connected, output -1.
For example:
user input:
7 6
1 3
2 3
3 4
3 5
4 5
5 6
1 6
, the program should output:
2
#include<iostream>using namespace std;int pre[1001];int u[2001],v[2001];int find(int x){ int i = x; while(pre[i]!=i) //查找根节点 i = pre[i]; //路径压缩 int j = x; int k; while(j!=i) { k = pre[j]; pre[j] = i; j = k; } return i;}void join(int x,int y){ int i,j; i = find(x); j = find(y); if(i!=j) pre[i] = j;}int main(){ int n,m; cin>>n>>m; int i,x,y; for(i=0;i<n;i++) pre[i] = i; for(i=0;i<m;i++) { cin>>x>>y; u[i] = x; v[i] = y; join(x,y); } cin>>x>>y; if(find(x)!=find(y)) //如果不连通就输出-1 cout<<"-1"<<endl; else //如果连通,寻找有几个关键站点 { int res = 0; for(i=0;i<n;i++) //因为数据很小,所以暴力枚举,从第一个站点开始判断是否是关键站点 { if(i==x||i==y) //如果i是x和y这两个需要判断是否连通的站点的其中一个就跳过 continue; for(int k=0;k<n;k++) //初始化pre数组 pre[k] = k; for(int j=0;j<m;j++) //按照输入顺序jion { if(u[j]==i||v[j]==i) //如果是i这个站点,就不在pre里面加链接这个站点的路径 continue; join(u[j],v[j]); } if(find(x)!=find(y)) //如果x和y不连通了,说明站点i是关键站点 res++; } cout<<res<<endl; } return 0;}
2005年浙江大学计算机复试 通畅工程 NYOJ608
畅通工程
注意:两个城市之间可以有多条道路相通,也就是说
3 3
1 2
1 2
2 1
这种输入也是合法的
当N为0时,输入结束,该用例不被处理。
4 21 34 33 31 21 32 35 21 23 5999 00
102998
这个题好烦,WA了好多次最后发现是一个小小小错误,还有说我超时,把cin全部换成scanf什么的了。还有一种写法比这个感觉稍微麻烦一点点,可以了解一下。
方法二:要将n个站点相连通,也就是要将每个连通路径的根节点相连通,求出根节点的数量num,最终还需要修建的路径数就为num-1。
#include<iostream>#include<stdio.h>using namespace std;int pre[1005];int find(int x){ int i = x; while(pre[i]!=i) i = pre[i]; return i;}int main(){ int n,m; int i,a,b,total,fa,fb; while(scanf("%d",&n) && n!=0) { scanf("%d",&m); total = n-1; //n个站点全部连通最少需要n-1条路径 for(i=1;i<=n;i++) pre[i] = i; for(i=1;i<=m;i++) { scanf("%d%d",&a,&b); fa = find(a); fb = find(b); if(fa!=fb) pre[fa] = fb; } for(i=1;i<=n;i++) { if(pre[i]!=i) //也就是有相连的路径 total --; } printf("%d\n",total); } return 0;}