跟hd1272不同、这道题就对成环不敏感了,能走就行,只在乎祖宗数量,祖宗之间形成不成环的链接
直接上代码把
#include<iostream>
using namespace std;
typedef long long ll;
inline ll read() {
ll c = getchar(), Nig = 1, x = 0;
while (!isdigit(c) && c != '-')c = getchar();
if (c == '-')Nig = -1, c = getchar();
while (isdigit(c))x = ((x << 1) + (x << 3)) + (c ^ '0'), c = getchar();
return Nig * x;
}
inline void Out(ll a)
{
if (a < 0)putchar('-'), a = -a;
if (a >= 10)Out(a / 10);
putchar(a % 10 + '0');
}
int f[1007];//按照数剧不大于1000开得全局数组
void intital_set(int x) {
for (int i = 1; i <= x; i++)
f[i] = i;//初始化数组
}
int getfather(int x) {
if (f[x] != x) {
f[x] = getfather(f[x]);
}
return f[x];//返回x的话相当于没压缩路径,达不到儿子直接连祖宗的效果,当然,也只是暂时的连着祖先,如果祖先后续当儿子,另说
}
void unionset(int x, int y) {
f[x] = getfather(x);//找一下祖先,不写的话找的只是父亲不是祖先,最后变成比较父亲一不一样
f[y] = getfather(y);//不能保证之前的祖先f【x】不变成别人的儿子。。。总感觉这段话怪怪的
if (f[x] == f[y])//祖先一样那没事了,一个家族的
return;
f[f[x]] = f[y];//x家族做y家族儿子//操作对象应该是祖先,两边不加多套f操作的是孩子的f值,会导致儿子换祖先,而且换的y还不是y家族的祖先
}
int main() {
int num_point;//点数
int num_road;//路径数
int x, y;
int time = 0;
intital_set(1000);
while (num_point = read()) {
if (!num_point) {
break;
}
num_road = read();
for (int i = 1; i <= num_road; i++) {
x = read();
y = read();
unionset(x, y);
}
for (int i = 1; i <= num_point; i++) {
if (f[i] == i) {//是祖先
time++;//祖先数量加1
}
}
Out(--time);//祖先数量-1等于完全联通所需的路程,即把祖先之间在连起来就行了
puts("");
intital_set(num_point);//数组状态返回
time = 0;//置0
}
}