这是一道最小生成树的题目
实际上,那些条件都是唬人的,根本没用。
对于条件(2):不妨假设A申请修建公路AB,B申请修建公路BC,C申请修建公路CA,构成了环。
然而,A申请AB,则有AB<AC
B申请BC,则有BC<BA
C申请CA,则有CA<CB
所以AB<AC<CB<AB 矛盾了
从而可得:对于一个图来说,节点的最短边不可能成环。
所以这题是裸最小生成树。
***************************************
然而问题并没有解决,
这道题有非常恶心的卡时。
首先是稠密图,5000*5000的边会炸空间,所以不能用kru
即使是prim,也不能用堆优化(复杂度会引入很大的E),老老实实的朴素n平方算法。
所以对于稠密图,有时候还不如不用堆。
对于边,直接计算即可了,不必存贮。
还有计算距离的时候记得把int转化成double。
**************************************
附代码:
#include<cstdio> #include<cstdlib> #include<iostream> #include<algorithm> #include<cstring> #include<cmath> #define MAXV 5005 #define INF 0x7fffffff using namespace std; int V; pair<int,int> P[MAXV]; double lenth(int x,int y){ return sqrt((double)(P[x].first-P[y].first)*(P[x].first-P[y].first)+(double)(P[x].second-P[y].second)*(P[x].second-P[y].second)); } double prim(){ double ret=0; double mincost[MAXV]; bool b[MAXV]={0}; for(int i=1;i<=V;i++){ mincost[i]=lenth(1,i); } while(1){ int v=0; for(int i=1;i<=V;i++){ if(!b[i]&&(!v||mincost[i]<mincost[v])){ v=i; } } if(v==0){ break; } b[v]=1; ret+=mincost[v]; for(int i=1;i<=V;i++){ mincost[i]=min(mincost[i],lenth(v,i)); } } return ret; } int main() { scanf("%d",&V); for(int i=1;i<=V;i++){ scanf("%d%d",&P[i].first,&P[i].second); } printf("%.2f",prim()); return 0; }
