刷题记录-luoguP1265 公路修建

xiaoxiao2021-02-28  120

这是一道最小生成树的题目

实际上,那些条件都是唬人的,根本没用。

对于条件(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; }

转载请注明原文地址: https://www.6miu.com/read-41185.html

最新回复(0)