zoukankan      html  css  js  c++  java
  • BZOJ3712 PA2014Fiolki(kruskal重构树)

      对合并过程建树。然后只需要按照时间顺序考虑每个反应就行了,时间顺序根据lca的深度确定。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    #define N 200010
    #define M 500010
    #define ll long long
    int n,m,k,a[N],p[N<<1],fa[N<<1],f[N<<1][20],deep[N<<1],t=0;
    ll ans=0;
    struct data{int to,nxt;
    }edge[N<<1];
    struct data2{int x,y,lca,i;
    }q[M];
    int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
    void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;}
    void dfs(int k)
    {
        for (int i=p[k];i;i=edge[i].nxt)
        {
            f[edge[i].to][0]=k;
            deep[edge[i].to]=deep[k]+1;
            dfs(edge[i].to);
        }
    }
    int lca(int x,int y)
    {
        if (deep[x]<deep[y]) swap(x,y);
        for (int j=19;~j;j--) if (deep[f[x][j]]>=deep[y]) x=f[x][j];
        if (x==y) return x;
        for (int j=19;~j;j--) if (f[x][j]!=f[y][j]) x=f[x][j],y=f[y][j];
        return f[x][0];
    }
    bool cmp(const data2&a,const data2&b)
    {
        return deep[a.lca]>deep[b.lca]||deep[a.lca]==deep[b.lca]&&a.i<b.i; 
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj3712.in","r",stdin);
        freopen("bzoj3712.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        n=read(),m=read(),k=read();
        for (int i=1;i<=n;i++) a[i]=read();
        for (int i=1;i<=n+m;i++) fa[i]=i;
        for (int i=1;i<=m;i++)
        {
            int x=read(),y=read();
            int p=find(x),q=find(y);
            fa[p]=fa[q]=n+i;
            addedge(n+i,p),addedge(n+i,q);
        }
        for (int i=n+m;i;i--)
        if (!f[i][0]) f[i][0]=i,dfs(i);
        for (int j=1;j<20;j++)
            for (int i=1;i<=n+m;i++)
            f[i][j]=f[f[i][j-1]][j-1];
        for (int i=1;i<=k;i++)
        q[i].x=read(),q[i].y=read(),q[i].lca=lca(q[i].x,q[i].y),q[i].i=i;
        sort(q+1,q+k+1,cmp);
        for (int i=1;i<=k;i++)
        if (find(q[i].x)==find(q[i].y))
        {
            int x=min(a[q[i].x],a[q[i].y]);
            ans+=x<<1;a[q[i].x]-=x,a[q[i].y]-=x;
        }
        cout<<ans;
        return 0;
    }
  • 相关阅读:
    【Codechef】Chef and Bike(二维多项式插值)
    USACO 完结的一些感想
    USACO 6.5 Checker Challenge
    USACO 6.5 The Clocks
    USACO 6.5 Betsy's Tour (插头dp)
    USACO 6.5 Closed Fences
    USACO 6.4 Electric Fences
    USACO 6.5 All Latin Squares
    USACO 6.4 The Primes
    USACO 6.4 Wisconsin Squares
  • 原文地址:https://www.cnblogs.com/Gloid/p/9723219.html
Copyright © 2011-2022 走看看