码迷,mamicode.com
首页 > Web开发 > 详细

UVA10369 Arctic Network

时间:2019-05-23 21:33:45      阅读:139      评论:0      收藏:0      [点我收藏+]

标签:printf   close   最大的   from   family   namespace   targe   最小   names   

传送门

求一棵最小生成树,要求:忽略树上s-1条边的边权后,最大的边最小。

(因为卫星频道是两两互达的,所以想把连接两个联通块之间的边权忽略必须用两个联通块都放置卫星频道。也就是至少要两个)

emmm...其实我本来想的是分层最短路那种动态规划,记录用了几次忽略机会。

假设已经求出答案最小生成树,忽略边权一定是忽略前s-1大的,那么所求即为第s大的边权。

考虑kruskal算法求最小生成树,每次都选最小的边加入...这样其实就保证了每条边都是当前最小的,那第s大一定也是最小的。

证明?在一棵最小生成树上,用一条非树边代替树边,那么第s大的边的边权要么不变要么变大。(来自学姐)

其实就是裸的最小生成树啊w

代码如下

 

技术图片
#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#define MogeKo qwq
#include<algorithm>
using namespace std;
const int maxn = 1e6;
int t,s,n,cnt,num;
int px[maxn],py[maxn],fa[maxn];

struct node {
    int from,to;
    double val;
    bool operator < (const node & N) const {
        return val < N.val;
    }
} e[maxn];

void add(int a,int b) {
    e[++cnt].from = a;
    e[cnt].to = b;
    e[cnt].val = sqrt( pow(px[a]-px[b],2) + pow(py[a]-py[b],2) );
}

int getfa(int x) {
    if(fa[x] == x)return x;
    else return fa[x] = getfa(fa[x]);
}

double kruskal() {
    for(int i = 1; i <= cnt; i++) {
        int x = getfa(e[i].from);
        int y = getfa(e[i].to);
        if(x == y)continue;
        fa[x] = y;
        num++;
        if(num == n-s)return e[i].val;
    }
}

int main() {
    scanf("%d",&t);
    while(t--) {
        scanf("%d%d",&s,&n);
        cnt = num = 0;
        for(int i = 1; i <= n; i++)
            fa[i] = i;
        for(int i = 1; i <= n; i++)
            scanf("%d%d",&px[i],&py[i]);
        for(int i = 1; i <= n; i++)
            for(int j = i+1; j <= n; j++)
                add(i,j);
        sort(e+1,e+cnt+1);
        printf("%.2lf\n",kruskal());
    }
    return 0;
}
View Code

 

UVA10369 Arctic Network

标签:printf   close   最大的   from   family   namespace   targe   最小   names   

原文地址:https://www.cnblogs.com/mogeko/p/10914238.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!