这一题,题目的大概意思是:有N台电脑,彼此直接能通信的最大距离为T,这些电脑因为地震损坏了,需要修理。修理之后,就可以跟其他的修理过的距离小于等于T的电脑通信,你需要回答的是某两台电脑是否能够通信。
简单的并查集的应用,只是加了一个限制条件。
输入N和T,下面N行为N个电脑的坐标。
再下面的是一直到文件结尾,输入O k,表示k电脑进行修理。输入S i j ,表示问你这两台电脑是否能够通信。
我用一个dis数组来存每两台电脑之间的距离,方便后面的判断。
下面是AC的代码,有详细的注释:
#include <iostream> #include <cmath> #include <cstdio> using namespace std; double dis[1005][1005]; //每台电脑与其他电脑之间的距离数组 int par[1005]; //并查集 bool vis[1005]; //标记该电脑是否已经修理过 int x[1005], y[1005]; int N, T; int finds(int x) //并查集查找函数 { if(x == par[x]) return x; else return par[x] = finds(par[x]); } void join(int x, int y) //并查集合并函数 { x = finds(x); y = finds(y); if(x != y) par[y] = x; } int main() { // freopen("data.txt", "r", stdin); int i, j, k, a , b; char str; scanf("%d%d", &N, &T); for(i = 1; i <= N; i++) //输入每台电脑坐标 { scanf("%d%d", &x[i], &y[i]); par[i] = i; //初始化并查集 vis[i] = false; //标记为没有修理过 } getchar(); for(i = 1; i <= N; i++) //计算每两台电脑直接的距离 { for(j = 1; j <= i; j++) { if(i == j) dis[i][j] = 0.0; else dis[i][j] = dis[j][i] = sqrt(double((x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j]))); } } while(scanf("%c", &str) != EOF) { if(str == 'O') //输入的是 O,要进行修理 { scanf("%d", &k); getchar(); for(i = 1; i <= N; i++) //与修理过的电脑之间距离的判断,判断是否能通信 { if(i != k && vis[i] && dis[k][i] <= (double)T) { join(i, k); //能就合并 } } vis[k] = true; //标记为修理过 } else if(str == 'S') //判断是否能通信 { scanf("%d%d", &a, &b); getchar(); if(finds(a) == finds(b)) //属于同一个并查集,就可以 printf("SUCCESS\n"); else printf("FAIL\n"); } } return 0; }
时间: 2024-10-09 00:49:56