POJ T1751 Highways
题解:
题意是建高速公路,求需要修那些路。先求出每个点到其他点的距离。因为题目中说有一些道路是已经建好的,所以咱们可以把他们之间的距离赋值为零,然后再进行最小生成树的求解。个人觉得Prim更适合这道题,因为最后只需要遍历一次dis数组,不为零的即为需要修的路。
输出时,需要修建的路的两点不管前后次序,指的是同一条边即可。
代码:
#include<cstdio>
#include<algorithm>
#include<cmath>
#define maxn 755
#define INF 0x3f3f3f3f
using namespace std;
struct Distance{
int v;
double d;
}dis[maxn];
struct Node{
int x,y;
}node[maxn];
int n,m;
double maps[maxn][maxn];
bool flag,vis[maxn];
void init(){
flag = true;
for(int i = 1; i <= n ; i++){
dis[i].d = INF;
vis[i] = false;
//for(int j = 1; j <= i; j++)
// i == j ? maps[i][j] = 0 : maps[i][j] = maps[j][i] = INF;
}
}
double solve(int i,int j){ //计算点与点之间的距离
double a = (node[i].x - node[j].x)*(node[i].x - node[j].x);
double b = (node[i].y - node[j].y)*(node[i].y - node[j].y);
return sqrt(a+b);
}
void Prim(int s){
dis[s].d = 0;
for(int i = 1; i <= n ; i++){
int p = 0;
double minn = INF;
for(int j = 1; j <= n; j++){
if(!vis[j] && minn > dis[j].d){
p = j;
minn = dis[j].d;
}
}
vis[p] = true;
for(int j = 1; j <= n ; j++){
if(!vis[j] && dis[j].d > maps[p][j]){
dis[j].d = maps[p][j];
dis[j].v = p;
}
}
}
}
int main(){
int u,v;
while(~scanf("%d",&n)){
init();
for(int i = 1; i <= n ; i++)
scanf("%d%d",&node[i].x,&node[i].y);
for(int i = 1; i <= n ; i++)
for(int j = 1; j <= i ; j++){
if(i == j)
maps[i][j] = 0;
else
maps[j][i] = maps[i][j] = solve(i,j);
}
scanf("%d",&m);
for(int i = 1; i <= m; i++){
scanf("%d%d",&u,&v);
maps[v][u] = maps[u][v] = 0;
}
Prim(1);
for(int i = 1 ; i <= n ; i++){
if(dis[i].d != 0){
printf("%d %d\n",i,dis[i].v);
flag = false;
}
}
if(!flag) printf("\n");
}
}