zoukankan      html  css  js  c++  java
  • 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
    ",ans<<1);
    }
    
  • 相关阅读:
    filter与compress
    groupby,分组
    按照属性排序,使用lambda与itemgetter,attrgetter
    python3-cookbook电子书在线文档
    numpy中的向量操作
    向量Vector
    defaultdict与OrderedDict
    heapq堆队列
    (转载)SVM-基础(一)
    决策树-剪枝算法(二)
  • 原文地址:https://www.cnblogs.com/devil-gary/p/8963141.html
Copyright © 2011-2022 走看看