奇怪的贪心居然过了
查看原帖
奇怪的贪心居然过了
578823
AsindE楼主2022/1/21 00:11
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int N = 600;
struct edge
{   
    int a, b;
    int dis;
    bool operator<(const edge &o){
        return dis < o.dis;
    }
}edges[N * N >> 1];
int idx;
struct pos
{
    int x, y;
}p[N];
int ne[N];
bool vis[N * N >> 1], vp[N];//vp存有无电话
int square(int x){
    return x * x;
}
int find(int x){
    if(x != ne[x]) return ne[x] = find(ne[x]);
    return ne[x];
}
void add(int a, int b){
    int ta = find(a), tb = find(b);
    if(ta - tb) ne[tb] = ta;
}
int main(){
    int n, k;
    scanf("%d%d", &k, &n);
    if(k < 2) k = 0;//只有一个电话就跟没有一样
    int num = n - k;//至少要连几个点
    for(int i = 0; i <= n; i++)
        ne[i] = i;
    for(int i = 0; i < n; i++)
        scanf("%d%d", &p[i].x, &p[i].y);
    for(int i = 0; i < n; i++)
        for(int j = i + 1; j < n; j++)
            edges[idx++] = {i, j, square(p[i].x - p[j].x) + square(p[i].y - p[j].y)};
    sort(edges, edges + idx);
    if(k)
    for(int i = idx - 1; i >= 0; i--){
        int a = edges[i].a, b = edges[i].b, cnt = 0;
        if(vp[a]) cnt++; if(vp[b]) cnt++;
        if(k >= 2){//电话有两个以上时尽量选择不含已有电话的两个点
            if(cnt == 2){
                vp[a] = vp[b] = true;
                k -= 2;
                if(!k) break;
            }
        }else if(k == 1)
            if(cnt == 1){
                vp[a] = vp[b] = true;
                k --;
                if(!k) break;
            }
    }
    for(int i = 0; i < num; i++)
        for(int j = 0; j < idx; j++){
            int a = edges[j].a, b = edges[j].b;
            if(!vis[j] && !(vp[a] && vp[b]) && find(a) != find(b)){
                vis[j] = true;
                add(a, b);
                break;
            }
        }
    for(int i = idx - 1; i >= 0; i--)
        if(vis[i]) {//从头到尾找,有就说明是答案
            printf("%.2lf", sqrt((double)edges[i].dis));
            break;
        }
}
2022/1/21 00:11
加载中...