次小生成树

一、思路:

先求最小生成树T,枚举添加不在T中的边,则添加后一定会形成环。

找到环上边值第二大的边(即环中属于T中的最大边),把它删掉,计算当前生成树的权值,取所有枚举修改的生成树的最小值,即为次小生成树。

二、代码

#include <algorithm>
#include <cstdio>
#include <cstring>
#include <math.h>
#include <iostream>
using namespace std;
#define MAX 0x3f3f3f3f
#define N 1010
int n;
double dis[N],map[N][N],Max[N][N];
int fa[N],used[N][N],logo[N];
struct Node
{
    int x,y,p;
} node[N];
double getdistence(int x1,int y1,int x2,int y2)
{
    double x=sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
    return x;
}
double Prim()
{
    double ans = 0;
    memset(logo, 0, sizeof(logo));
    memset(Max, 0, sizeof(Max));
    memset(used, 0, sizeof(used));
    logo[1] = 1;
    fa[1] = 0;
    dis[1] = 0;
    for (int i = 2; i <= n; i++)
    {
        dis[i] = map[1][i];
        fa[i] = 1;
    }

    for (int i = 1; i < n; i++)
    {
        double min1 = MAX;
        int now = -1;
        for (int j = 1; j <= n; j++)
        {
            if (!logo[j] && min1 > dis[j])
            {
                min1 = dis[j];
                now = j;
            }
        }
        if (min1 == MAX)
            return -1;

        ans += min1;
        logo[now] = 1;
        used[now][fa[now]] = used[fa[now]][now] = 1;
        for (int j = 1; j <= n; j++)
        {
            if (logo[j] && j != now)
                Max[j][now] = Max[now][j] = max(Max[j][fa[now]], dis[now]);
            if (!logo[j] && dis[j] > map[now][j])
            {
                dis[j] = map[now][j];
                fa[j] = now;
            }
        }
    }

    return ans;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        memset(map,0,sizeof(map));
        scanf("%d",&n);
        for(int i=1; i<=n; i++)
            scanf("%d %d %d",&node[i].x,&node[i].y,&node[i].p);
        for(int i=1; i<=n; i++)
            for(int j=1; j<=n; j++)
                map[i][j]=getdistence(node[i].x,node[i].y,node[j].x,node[j].y);
        double sum=Prim();

        double ans=0;
        for(int i=1; i<=n; i++)
            for(int j=1; j<=n; j++)
            {
                if(i!=j)
                {
                    if(used[i][j])
                        ans=max(ans,(node[i].p+node[j].p)*1.0/(sum-map[i][j]));
                    else
                        ans=max(ans,(node[i].p+node[j].p)*1.0/(sum-Max[i][j]));
                }
            }
        printf("%.2lf\n",ans);
    }
    return 0;
}

 

posted @ 2017-10-11 20:37  爱国呐  阅读(301)  评论(0)    收藏  举报