洛谷P2212 [USACO14MAR]澆地Watering the Fields

https://www.luogu.org/problem/show?pid=2212
很神奇啊
一共2000個點,那麼最多有4e6條邊;
如果通prim取最小生成樹的話就是吻過的;
然後我又試了一下kruskal的算法
結果炸了;
必須要安按秩合併,光路徑壓縮是不行的;
假如有一個數據,不斷在合併的時候合併一個樹的根節點,那麼路徑壓縮有沒有用;
最後一下子路徑壓縮,就可以卡到O(n)
加上遞歸和一個if,還有一開始排序的時間,就直接炸掉了;

#include<bits/stdc++.h>
#define Ll long long
using namespace std;
const Ll N=2e3+5;
struct cs{int x,y,v;}a[N*N];
int x[N],y[N],ll,f[N],siz[N];
int n,m,ans,sum;
bool cmp(cs x,cs y){return x.v<y.v;}
int get(int x){if(f[x]==0)return x;return f[x]=get(f[x]);}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)scanf("%d%d",&x[i],&y[i]);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++){
            int v=(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]);
            if(v>=m)a[++ll].x=i,a[ll].y=j,a[ll].v=v;
        }
    sort(a+1,a+ll+1,cmp);
    for(int i=1;i<=n;i++)    siz[i]=1;
    for(int i=1;i<=ll;i++)
    {
        if(get(a[i].x)!=get(a[i].y)){
            ans+=a[i].v;sum++;
            int tx=get(a[i].x),ty=get(a[i].y);
//            f[tx]=ty;
            if(siz[tx]>siz[ty])
                f[ty]=tx,siz[tx]+=siz[ty],siz[ty]=0;
                else    f[tx]=ty,siz[ty]+=siz[tx],siz[tx]=0;
        }
    }
    if(sum<n-1)ans=-1;
    printf("%d",ans);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章