Input测试输入包含若干测试用例。每个测试用例的第1行给出两个正整数,分别是城镇数目N ( < 1000 )和道路数目M;随后的M行对应M条道路,每行给出一对正整数,分别是该条道路直接连通的两个城镇的编号。为简单起见,城镇从1到N编号。
注意:两个城市之间可以有多条道路相通,也就是说
3 3
1 2
1 2
2 1
这种输入也是合法的
当N为0时,输入结束,该用例不被处理。
Output对每个测试用例,在1行里输出最少还需要建设的道路数目。
Sample Input
4 2 1 3 4 3 3 3 1 2 1 3 2 3 5 2 1 2 3 5 999 0 0
Sample Output
1 0 2 998 Huge input, scanf is recommended.
Hint
Hint
刚刚做了一道cf上的并查集,然后去找并查集去做。
这道题,把能连上的路先都连上,最后遍历一下所以的点,看看有多少个不同的根结点,然后根节点数减一就是最后要连接的路的条数。
1 #include<stdio.h> 2 #include<algorithm> 3 #include<string> 4 #include<iostream> 5 #include<string.h> 6 #include<cmath> 7 #define mem(a, b) memset(a, b, sizeof(a)) 8 #define N 1001 9 #define LL long long 10 using namespace std; 11 int n, m, k, pre[N], vis[N]; 12 int fi(int x){ 13 return pre[x]==x?x:pre[x]=fi(pre[x]); //找根节点 14 } 15 void uni(int x, int y){//连接两条路 16 int fx=fi(x), fy=fi(y);//找两条路分别的节点 17 if(fx!=fy){//如果一样,说明已经连接,不然就把它连接起来 18 pre[fy]=fx; 19 } 20 } 21 int main() { 22 while(1){ 23 cin>>n; 24 if(n==0){ 25 break; 26 } 27 cin>>m; 28 int cnt=0; 29 for(int i=1; i<=n; i++){ 30 pre[i]=i;//一开始每个点的根节点都是自己 31 } 32 for(int i=1; i<=m; i++){ 33 int a, b; 34 cin>>a>>b; 35 uni(a,b);//连接 36 } 37 mem(vis, 0); 38 for(int i=1; i<=n; i++){ 39 if(vis[fi(i)]==0){ 40 cnt++; 41 vis[fi(i)]=1; 42 } 43 } 44 cout<<cnt-1<<endl; 45 } 46 47 return 0; 48 }