思路:最小生成树+prime
分析:只要按照prime的思路求出所有的边,然后输出的时候判断是否是已经建好的即可。
注意:可能出现已经把所有的边都建好的情况,这个时候不用输出
代码:
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<cmath> using namespace std; #define MAXN 1000 int n , m; int vis[MAXN]; int pre[MAXN]; double lowcost[MAXN]; double G[MAXN][MAXN]; struct Point{ int x; int y; }p[MAXN]; struct Edge{ int x; int y; }ans[MAXN] , exist[MAXN]; /*初始化边的长度*/ void init(){ for(int i = 1 ; i <= n ; i++){ pre[i] = 1; for(int j = 1 ; j <= n ; j++){ double tmp_x = (p[i].x-p[j].x)*(p[i].x-p[j].x); double tmp_y = (p[i].y-p[j].y)*(p[i].y-p[j].y); G[i][j] = sqrt(tmp_x + tmp_y); } } } /*prime求解最小生成树*/ void prime(){ memset(vis , 0 , sizeof(vis)); int pos , cnt; vis[1] = 1; cnt = 0; for(int i = 1 ; i <= n ; i++) lowcost[i] = G[1][i]; for(int i = 1 ; i <= n ; i++){ pos = -1; for(int j = 1 ; j <= n ; j++){ if(!vis[j] && (pos == -1 || lowcost[j] < lowcost[pos])) pos = j; } if(pos == -1) break; vis[pos] = 1; ans[cnt].x = pre[pos]; ans[cnt++].y = pos; for(int j = 1 ; j <= n ; j++){ if(!vis[j] && lowcost[j] > G[j][pos]){ lowcost[j] = G[j][pos]; pre[j] = pos; } } } } /*输出*/ void output(){ int flag , cnt; cnt = 0; for(int i = 0 ; i < n-1 ; i++){ flag = 0; for(int j = 0 ; j < m ; j++){ if(ans[i].x == exist[j].x && ans[i].y == exist[j].y){ flag = 1; break; } else if(ans[i].x == exist[j].y && ans[i].y == exist[j].x){ flag = 1; break; } } if(!flag){ cnt++; printf("%d %d\n" , ans[i].x , ans[i].y); } } } int main(){ int begin , end; scanf("%d" , &n); for(int i = 1 ; i <= n ; i++) scanf("%d%d" , &p[i].x , &p[i].y); init(); scanf("%d" , &m); for(int i = 0 ; i < m ; i++){ scanf("%d%d" , &begin , &end); G[begin][end] = G[end][begin] = 0; exist[i].x = begin; exist[i].y = end; } prime(); output(); return 0; }
时间: 2024-10-29 08:15:58