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;
}
原文地址:https://www.cnblogs.com/Gloid/p/9723219.html