判断最小生成树是否唯一

题目链接: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\n",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;
}


 

posted @ 2018-11-10 16:10  Let_Life_Stop  阅读(1245)  评论(0编辑  收藏  举报