hdoj 1875 通畅工程再续 最小生成树

来源:互联网 发布:mac baren烟丝购买 编辑:程序博客网 时间:2024/05/16 06:07

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1875

题目大意:中文题

分析:这题,就是附加了条件的最小生成树,要求最小生成树上的权大于等于10,小于等于1000,问能不能找到这样一棵生成树,以及生成树的权之和。如果我们直接贴最小生成树的板子,那么当两个点的最段距离<10,该如何pass掉,然后找他们的次短距离,如果还不满足,依次类推。那么我们不妨在处理点与点之间的距离时处理一下,让不满足条件的距离等于INF,那么使用最小生成树算法时自然不会选到长为INF的边,如果选到了,说明没有满足条件的生成树。

code:

#include<cstdio>
#include<cmath>
#define min(a,b) (a<b?a:b)
const int MAXV=100+5,INF=999999;
double mincost[MAXV];
bool used[MAXV];
int x[MAXV],y[MAXV];
double cost[MAXV][MAXV];
int V;
double dist(double x1,double y1,double x2,double y2){
    return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
double prim(){
    for(int i=1;i<=V;++i)
        mincost[i]=INF,used[i]=false;
    mincost[1]=0.0;
    double res=0.0;
    while(true){
        int v=-1;
        for(int u=1;u<=V;++u){
            if(!used[u]&&(v==-1||mincost[u]<mincost[v]))v=u;
        }
        if(v==-1)break;
        used[v]=true;
        res+=mincost[v];
        for(int u=1;u<=V;++u){
            mincost[u]=min(mincost[u],cost[v][u]);
        }
    }
    return res;
}
int main(void){
    int T;scanf("%d",&T);
    while(T--){
        scanf("%d",&V);
        for(int i=1;i<=V;++i)
            scanf("%d%d",&x[i],&y[i]);
        for(int i=1;i<=V;++i)
            for(int j=1;j<=i;++j){
            double temp=dist((double)x[i],(double)y[i],(double)x[j],(double)y[j]);
            cost[i][j]=cost[j][i]= (temp>=10&&temp<=1000?temp:INF);
            }
        double distance=prim();
       if(distance>=INF)printf("oh!\n");
       else{
        double cost=100*distance;
        printf("%.1lf\n",cost);
       }
    }
}

0 0