【问题描述】
某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇。省政府“畅通工程”的目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要互相间接通过道路可达即可)。问最少还需要建设多少条道路?
【输入形式】
每个测试用例的第1行给出两个正整数,分别是城镇数目_n_(n<1000)和道路数目_m_,随后的_m_行对应_m_条道路,每行给出一对正整数,分别是该条道路直接连通的两个城镇的编号。为简单起见,城镇从1到_n_编号。注意两个城市之间可以有多条道路相通,也就是说:
3 3
1 2
1 2
2 1
这种输入也是合法的。
【输出形式】对每个测试用例,在一行里输出最少还需要建设的道路数目。
【样例输入】
3 3
1 2
1 3
2 3
【样例输出】
0
【样例说明】
测试数据的文件名为in.txt
【评分标准】
该题目有10个测试用例,每通过一个测试用例,得10分。
思路
由于老师明说了是并查集的题,所以……就不用动脑子了
并查集
- 根据给定的已有条件初始化disjoint sets
- 找到disjoint sets的数量记作root_num,我们需要再建的路就是把这些sets连起来的路,所以最少的路数即为root_num - 1
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
| #include<iostream> #include<fstream> #include<vector> using namespace std;
vector<int> parent; vector<int> rnk;
void Init(int n){ for(int i = 0; i <= n; i++){ parent.push_back(i); rnk.push_back(0); } } int Find(int x){ if(parent[x] != x){ parent[x] = Find(parent[x]); } return parent[x]; }
void Union(int x, int y){ int rx = Find(x); int ry = Find(y); if(rx == ry){ return; } if(rnk[ry] > rnk[rx]){ parent[rx] = ry; }else{ if(rnk[rx] == rnk[ry]){ rnk[rx]++; } parent[ry] = rx; } }
int Root_Num(int n){ int ret; for(int i = 1; i <= n; i++){ if(Find(i) == i){ ret++; } } return ret; }
int main(){ ifstream file("in.txt"); int n, data_nums; file >> n >> data_nums; Init(n); int a, b; while(data_nums--){ file >> a >> b; Union(a, b); } cout << Root_Num(n) - 1; return 0; }
|
版权声明: 此文章版权归Vks所有,如有转载,请注明来自原作者