洛谷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);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章