zoukankan      html  css  js  c++  java
  • 【BZOJ-3712】Fiolki LCA + 倍增 (idea题)

    3712: [PA2014]Fiolki

    Time Limit: 30 Sec  Memory Limit: 128 MB
    Submit: 303  Solved: 67
    [Submit][Status][Discuss]

    Description

    化学家吉丽想要配置一种神奇的药水来拯救世界。
    吉丽有n种不同的液体物质,和n个药瓶(均从1到n编号)。初始时,第i个瓶内装着g[i]克的第i种物质。吉丽需要执行一定的步骤来配置药水,第i个步骤是将第a[i]个瓶子内的所有液体倒入第b[i]个瓶子,此后第a[i]个瓶子不会再被用到。瓶子的容量可以视作是无限的。
    吉丽知道某几对液体物质在一起时会发生反应产生沉淀,具体反应是1克c[i]物质和1克d[i]物质生成2克沉淀,一直进行直到某一反应物耗尽。生成的沉淀不会和任何物质反应。当有多于一对可以发生反应的物质在一起时,吉丽知道它们的反应顺序。每次倾倒完后,吉丽会等到反应结束后再执行下一步骤。
    吉丽想知道配置过程中总共产生多少沉淀。

    Input

    第一行三个整数n,m,k(0<=m<n<=200000,0<=k<=500000),分别表示药瓶的个数(即物质的种数),操作步数,可以发生的反应数量。
    第二行有n个整数g[1],g[2],…,g[n](1<=g[i]<=10^9),表示初始时每个瓶内物质的质量。
    接下来m行,每行两个整数a[i],b[i](1<=a[i],b[i]<=n,a[i]≠b[i]),表示第i个步骤。保证a[i]在以后的步骤中不再出现。
    接下来k行,每行是一对可以发生反应的物质c[i],d[i](1<=c[i],d[i]<=n,c[i]≠d[i]),按照反应的优先顺序给出。同一个反应不会重复出现。

    Output

    Sample Input

    3 2 1
    2 3 4
    1 2
    3 2
    2 3

    Sample Output

    6

    HINT

    Source

    鸣谢Jcvb

    Solution

    idea比较好的一道题,不是特别容易想到

    很容易发现是树形结构,那么考虑把树建出来

    这里自己想到了,但是忽略了一点,自己的想法是想如果x流进y,那么就建树边x-->y,但实际上是不可以的,正确的做法是新建一个节点X',x-->X',y-->X',然后把y的标号换为X',这样就可以了,很容易理解;(但要注意的是,这里建出的实际上是森林,可以DFS按时间戳划分)

    那么题目就转化为树上的了,那么一个反应的询问,实际上就是找LCA,那么用倍增去找LCA即可

    注意反应的顺序,那么可以按LCA的深度为第一关键字,id为第二关键字排序,统计答案就可以了

    idea:

    模型的转化,就如同SDOI2016省队集训R1Day4T3,转化到树上,就能简化问题,利用其性质得出结果

    注意Code时的细节,避免手误

    像如此转化成树的问题,不要总想直接转化,可以考虑加额外的点,这种思想 BZOJ3551Peaks加强版 的Kruskal重构树中有很好的体现

    Code

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    using namespace std;
    int read()
    {
        int x=0,f=1; char ch=getchar();
        while (ch<'0' || ch>'9') {if (ch=='-')f=-1; ch=getchar();}
        while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
        return x*f; 
    }
    #define maxn 500010
    long long ans;
    struct EdgeNode{int next,to;}edge[maxn<<1];
    int head[maxn],cnt=1;
    int n,m,k,t,g[maxn],fa[maxn],father[maxn][21],deep[maxn],dfn[maxn];
    struct Node
    {
        int x,y,dp,id;
        Node () {}
        Node (int a,int b,int c,int d) {x=a;y=b;dp=c;id=d;}
        bool operator < (const Node & A) const
            {return dp==A.dp?id<A.id:dp>A.dp;}
    }tmp[maxn];int tot;
    void add(int u,int v) {cnt++;edge[cnt].next=head[u];head[u]=cnt;edge[cnt].to=v;}
    void insert(int u,int v) {add(u,v);add(v,u);}
    void DFS(int now,int tim)
    {
        dfn[now]=tim;
        for (int i=1; i<=20; i++)
            if ((1<<i)<=deep[now]) father[now][i]=father[father[now][i-1]][i-1];
                else break;
        for (int i=head[now]; i; i=edge[i].next)
            if (edge[i].to!=father[now][0])
                {
                    deep[edge[i].to]=deep[now]+1;
                    father[edge[i].to][0]=now;
                    DFS(edge[i].to,tim);
                }
    }
    int LCA(int x,int y)
    {
        if (deep[x]<deep[y]) swap(x,y);
        int dd=deep[x]-deep[y];
        for (int i=0; (1<<i)<=dd; i++)
            if (dd&(1<<i)) x=father[x][i];
        for (int i=20; i>=0; i--)
            if (father[x][i]!=father[y][i])
                x=father[x][i],y=father[y][i];
        if (x==y) return x;
        return father[x][0];
    }
    int main()
    {
        n=read(); m=read(); k=read();
        for (int i=1; i<=n; i++) g[i]=read();
        for (int i=1; i<=n; i++) fa[i]=i;
        for (int x,y,i=1; i<=m; i++) 
            x=read(),y=read(),insert(n+i,fa[x]),insert(n+i,fa[y]),fa[y]=n+i;
        for (int i=n+m; i; i--) if (!father[i][0]) DFS(i,++t);
    //    printf("%d
    ",t);
        for (int x,y,i=1; i<=k; i++)
            {
                x=read(),y=read();
                if (dfn[x]==dfn[y]) tmp[++tot]=Node(x,y,deep[LCA(x,y)],i);
            }
        sort(tmp+1,tmp+tot+1);
        for (int x,y,cd,i=1; i<=tot; i++)
            x=tmp[i].x,y=tmp[i].y,cd=min(g[x],g[y]),g[x]-=cd,g[y]-=cd,ans+=(long long)cd;
    //    printf("%d
    ",tot);
        printf("%lld",(long long)ans<<1);
        return 0;
    }

    我是不会告诉你,WA成这个狗样是因为自己快速读入写错了,智障+10

  • 相关阅读:
    linux工具-awk
    linux工具-sed
    linux工具-grep
    linux编程-bash
    linux命令-sort
    linux命令-seq
    linux命令-find
    linux命令-split
    IDEA去除xml文件中的屎黄色背景
    Rabbit 基于cloud 的配置使用结构流程
  • 原文地址:https://www.cnblogs.com/DaD3zZ-Beyonder/p/5536227.html
Copyright © 2011-2022 走看看