Zjr506的捕貓計劃

題目描述

Zjr506很喜歡貓,某一天他突然心血來潮,想捕捉學校裏活動的貓。
爲了捕貓,Zjr506在校園中放置了N個木樁,當他見到有貓進入他的狩獵範圍後,就會以迅雷不及掩耳的速度在一些木樁之間繞上藩籬以困住這些貓。
一段時間後,Zjr506在繞了M個藩籬後興高采烈的離開了。作爲正義的使者,Ztxz16不忍心看到這些貓受到折磨,於是決定拆除一些藩籬讓所有的貓都逃出去。因爲Zjr506的巧妙設計,藩籬不會在除木樁之外的地方相交。這些藩籬構成了一些封閉的區域,每一個區域中都有一隻貓。
因爲Zjr506製造這些藩籬也不容易,所以Ztxz16希望拆除的藩籬總長度儘量小,現在他希望你告訴他最小的總長度。

數據範圍

N <= 10000, M <= 50000

題目描述是有問題的,有一種特殊情況即一個藩籬經過不止兩個木樁,可以是三個四個,因爲題目僅僅說明藩籬不會在除木樁之外的地方相交。除去這種情況,題解的做法就是對的。

那麼考慮要拆除一些藩籬,使圖中不在任何環,也就是說刪完藩籬後的圖會成爲一棵樹,那麼我們只要做一遍最大生成樹即可。

代碼

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
const int maxn=10000+5;const int maxm=50000+5;
int i,j,f[maxn],n,m;
double sum;
struct ar{
    int x,y;double d;
}b[maxm],z[maxn];
bool cmp(ar x,ar y){
    return x.d>y.d;
}
double sqr(int x){
    double a=x;
    return a*a;
}
int get(int x){
    if (f[x]==0) return x;
    return f[x]=get(f[x]);
}
int main(){
    scanf("%d%d",&n,&m);
    fo(i,1,n) scanf("%d%d",&z[i].x,&z[i].y);
    fo(i,1,m){
        scanf("%d%d",&b[i].x,&b[i].y);
        int x=b[i].x,y=b[i].y;
        b[i].d=sqr(z[x].x-z[y].x)+sqr(z[x].y-z[y].y);
        b[i].d=sqrt(b[i].d);
        sum+=b[i].d;
    }
    sort(b+1,b+1+m,cmp);
    fo(i,1,m){
        int x=b[i].x,y=b[i].y;
        x=get(x),y=get(y);
        if (x!=y){
            sum-=b[i].d;
            f[x]=y;
        }
    }
    printf("%.5lf\n",sum);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章