zoukankan      html  css  js  c++  java
  • 判断最小生成树是否唯一

    题目链接:https://vjudge.net/contest/67265#problem/B

    具体思路:首先,跑一遍最小生成树,然后在求最小生成树的过程中,记录任意两个城市之间的最大边权,然后再暴力,枚举任意两个城市,然后如果这两个城市在最小生成树上有直接边相连,套用公式,(q[i].num+q[j].num)/(mst- road[i][j]),如果没有直接边相连,就套用公式(q[i].num+q[j].num)/(mst-maxx[i][j]),这里的maxx[i][j]指的是两个点之间的最大边权,然后输出最大结果就好了。(这题对精度限制还挺高的)。

    AC代码:

    #include<iostream>
    #include<string>
    #include<cstring>
    #include<iomanip>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<map>
    #include<stdio.h>
    #include<algorithm>
    #include<set>
    using namespace std;
    # define ll long long
    # define inf 0x3f3f3f3f
    # define maxn 1000+100
    # define eps 1e-6
    double road[maxn][maxn];
    int used[maxn][maxn];
    int vis[maxn];
    double maxx[maxn][maxn];
    int father[maxn];
    double dis[maxn];
    int n;
    double mst;
    struct node
    {
        int x,y;
        int  num;
    } q[maxn];
    void init()
    {
        memset(vis,0,sizeof(vis));
        memset(maxx,0,sizeof(maxx));
        memset(used,0,sizeof(used));
        memset(dis,inf,sizeof(dis));
    }
    void prim()
    {
        vis[1]=1;
        for(int i=1; i<=n; i++)
        {
            dis[i]=road[1][i];
            father[i]=1;
        }
        for(int i=1; i<n; i++)
        {
            double minn=inf;
            int index=-1;
            for(int j=1; j<=n; j++)
            {
                if(vis[j]==0&&minn>dis[j])
                {
                    minn=dis[j];
                    index=j;
                }
            }
            if(index==-1)break;
            vis[index]=1;
            mst+=minn;
            used[father[index]][index]=used[index][father[index]]=1;//记录该边是否在最小生成树上。
            for(int j=1; j<=n; j++)
            {
                if(vis[j]==0)
                {
                    if(dis[j]>road[index][j])
                    {
                        father[j]=index;
                        dis[j]=road[index][j];
                    }
                }
                else if(vis[j]&&j!=index)
                {
                    maxx[index][j]=maxx[j][index]=max(maxx[father[index]][j],dis[index]);
    // j - > index 是 k - > father[index] 的一部分。
                }
            }
        }
        return ;
    }
    void judge()
    {
        double ans=-1.0;
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=n; j++)
            {
                if(i==j)continue;
                if(used[i][j])
                {
                    ans=max(ans,(q[i].num+q[j].num)*1.0/(mst-road[i][j]));
                }
                else
                {
                    ans=max(ans,(q[i].num+q[j].num)*1.0/(mst-maxx[i][j]));
                    // cout<<i<<" "<<j<<" "<<maxx[i][j]<<endl;
                }
            }
        }
        printf("%.2lf
    ",ans);
        return ;
    }
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--)
        {
            init();
            scanf("%d",&n);
            for(int i=1; i<=n; i++)
            {
                scanf("%d%d%d",&q[i].x,&q[i].y,&q[i].num);
            }
            for(int i=1; i<=n; i++)
            {
                for(int j=1; j<=n; j++)
                {
                        road[i][j]=road[j][i]=sqrt((q[i].x-q[j].x)*(q[i].x-q[j].x)*1.0+(q[i].y-q[j].y)*(q[i].y-q[j].y)*1.0);
                }
            }
            mst=0.0;
            prim();
            judge();
        }
        return 0;
    }
    
    
    
  • 相关阅读:
    cdoj 841 休生伤杜景死惊开 逆序数/树状数组
    Codeforces Round #296 (Div. 1) B. Clique Problem 贪心
    【NOIP2014】联合权值 树上dp
    【NOIP2014】生活大爆炸版石头剪刀布
    BZOJ 2756: [SCOI2012]奇怪的游戏 网络流/二分
    BZOJ 1012: [JSOI2008]最大数maxnumber 单调队列/线段树/树状数组/乱搞
    BZOJ 1036: [ZJOI2008]树的统计Count 树链剖分
    BZOJ 1854: [Scoi2010]游戏 并查集
    BZOJ 1008 [HNOI2008]越狱 排列组合
    BZOJ 1003 物流运输trans dijstra+dp
  • 原文地址:https://www.cnblogs.com/letlifestop/p/10262829.html
Copyright © 2011-2022 走看看