BZOJ3712[PA2014]Fiolki 建图+倍增lca

居然是一道图论题 毫无思路

我们对于每一次的融合操作 \((a,b)\) 建一个新点\(c\) 并向\(a,b\)连边 再将\(b\)瓶当前的位置赋成\(c\) 这样子我们就可以建成一个森林

现在枚举每一种反应\(M_i\) 看他在森林里是否存在\(lca\) 存在就相当于会在\(lca\)处发生反应 因为有反应的顺序 我们对\(lca\)排序后先做\(lca\)深度大的 深度相同就先做\(M\)\(id\)小的 这样就满足题意了

我交了半天 居然是因为倍增数组写错了 真菜o(╥﹏╥)o

#include<bits/stdc++.h>
using namespace std;
#define FO(x) {freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);}
#define pa pair<int,int>
#define mod 1000000007
#define ll long long
#define mk make_pair
#define pb push_back
#define fi fisrt
#define se second
#define cl(x) memset(x,0,sizeof x)
#ifdef Devil_Gary
#define bug(x) cout<<(#x)<<" "<<(x)<<endl
#define debug(...) fprintf(stderr, __VA_ARGS__)
#else
#define bug(x)
#define debug(...)
#endif
const int INF = 0x7fffffff;
const int N=2e5+5;
//*
char *TT,*mo,but[(1<<15)+2];
#define getchar() ((TT==mo&&(mo=(TT=but)+fread(but,1,1<<15,stdin),TT==mo))?-1:*TT++)//*/
inline int read(){
    int x=0,rev=0,ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')rev=1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    return rev?-x:x;
}
struct Edge{
    int v,nxt;
}e[N<<1];
struct data{
    int u,v,f,dis,id;
}a[N*3];
ll ans; 
int g[N],n,cnt,tot,m,K,head[N<<1],dep[N<<1],bin[23]={1},f[N<<1][22],pos[N];
void add(int u,int v){
    e[++tot].v=v,e[tot].nxt=head[u],head[u]=tot;
}
bool cmp(const data&a,const data&b){
    return a.dis==b.dis?a.id<b.id:a.dis>b.dis;
}
void dfs(int x){
    for(int i=1;i<=19&&bin[i-1]<=dep[x];i++) f[x][i]=f[f[x][i-1]][i-1];
    for(int i=head[x];i;i=e[i].nxt){
        int j=e[i].v;
        dep[j]=dep[x]+1,f[j][0]=x,dfs(j);
    }
}
int LCA(int u,int v){
    if(dep[u]<dep[v]) swap(u,v);
    int ret=dep[u]-dep[v];
    for(int i=19;~i;--i){
        if(bin[i]&ret){
            u=f[u][i];
        }
    }
    if(u==v) return u;
    for(int i=19;~i;i--){
        if(f[u][i]!=f[v][i]){
            u=f[u][i],v=f[v][i];
        }
    }
    return f[u][0];
}
int main(){
#ifdef Devil_Gary
    freopen("in.txt","r",stdin);
#endif
    n=read(),m=read(),K=read(); 
    for(int i=1;i<=20;i++) bin[i]=bin[i-1]<<1;
    for(int i=1;i<=n;i++) g[i]=read(),pos[i]=i;
    for(int i=1,x,y,z;i<=m;i++) {
        x=read(),y=read(),z=n+i;
        add(z,pos[x]),add(z,pos[y]),pos[y]=z;
    }
    for(int i=n+m;i;--i) if(!f[i][0]) dfs(i);
    for(int i=1;i<=K;i++){
        #define i cnt
        a[++i].u=read(),a[i].v=read(),a[i].f=LCA(a[i].u,a[i].v),a[i].dis=dep[a[i].f],a[i].id=i; 
        #undef i
        if(!a[cnt].f) --cnt;
    } 
    sort(a+1,a+cnt+1,cmp); 
    for(int i=1,u,v,mn;i<=cnt;i++){
        if(!a[i].f) continue;
        u=a[i].u,v=a[i].v;
        mn=min(g[u],g[v]);
        g[u]-=mn,g[v]-=mn,ans+=mn;
    } 
    printf("%lld\n",ans<<1);
}
posted @ 2018-04-27 16:31  Devil_Gary  阅读(223)  评论(0编辑  收藏  举报