zoukankan      html  css  js  c++  java
  • Fiolki题解

    问题 B: Fiolki

    时间限制: 3 Sec  内存限制: 128 MB

    题目描述

    化学家吉丽想要配置一种神奇的药水来拯救世界。

    吉丽有n种不同的液体物质,和n个药瓶(均从1到n编号)。初始时,第i个瓶内装着g[i]克的第i种物质。吉丽需要执行一定的步骤来配置药水,第i个步骤是将第a[i]个瓶子内的所有液体倒入第b[i]个瓶子,此后第a[i]个瓶子不会再被用到。瓶子的容量可以视作是无限的。

    吉丽知道某几对液体物质在一起时会发生反应产生沉淀,具体反应是1克c[i]物质和1克d[i]物质生成2克沉淀,一直进行直到某一反应物耗尽。生成的沉淀不会和任何物质反应。当有多于一对可以发生反应的物质在一起时,吉丽知道它们的反应顺序。每次倾倒完后,吉丽会等到反应结束后再执行下一步骤。

    吉丽想知道配置过程中总共产生多少沉淀。

    输入

    第一行三个整数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]),按照反应的优先顺序给出。同一个反应不会重复出现。

    输出

    配置过程中总共产生多少沉淀。

    样例输入

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

    样例输出

    6

     乱搞压正解,暴力出奇迹。
     数据水到一定地步,当时本来期望打50分的暴力A了……
     
      1 #include<iostream>
      2 #include<cstdlib>
      3 #include<cstdio>
      4 #include<cstring>
      5 #include<queue>
      6 #include<algorithm>
      7 #include<cmath>
      8 #define N 200005
      9 using namespace std;
     10 int n,m,t,zz2;
     11 int g[N],a[N],b[N];
     12 int f[N][2],zz;
     13 struct ro{
     14     int to,l,from;
     15     int next;
     16     bool friend operator > (ro a,ro b)
     17     {
     18         return a.l>b.l;
     19     }
     20 }road[1000005],road2[1000006];
     21 void build(int x,int y,int z){
     22     zz++;
     23     road[zz].to=y;
     24     road[zz].from=x;
     25     road[zz].l=z;
     26     road[zz].next=a[x];
     27     a[x]=zz;
     28 }
     29 void build2(int x,int y){
     30     zz2++;
     31     road2[zz2].from=x;
     32     road2[zz2].to=y;
     33     road2[zz2].next=b[x];
     34     b[x]=zz2;
     35 }
     36 int fa[N];
     37 int find(int x){
     38     if(fa[x]==x)return x;
     39     fa[x]=find(fa[x]);
     40     return fa[x];
     41 }
     42 long long hav[N];
     43 void hb(int a,int b){
     44     int x=find(a);
     45     int y=find(b);
     46     fa[x]=y;
     47     hav[y]+=hav[x];
     48     build2(y,x);
     49 }
     50 bool cle[N],cle2[N];
     51 priority_queue<ro,vector<ro>,greater<ro > > q1;
     52 void dfs(int x,int tt){
     53     //cout<<x<<endl
     54     if(!cle2[x])
     55     {
     56         for(int i=a[x];i>0;i=road[i].next)
     57         {
     58             int y=road[i].to;
     59             if(find(y)==tt)
     60             {
     61                 q1.push(road[i]);
     62             }
     63         }
     64     }
     65     bool yx=1;
     66     for(int i=b[x];i>0;i=road2[i].next)
     67     {
     68         int y=road2[i].to;
     69         if(!cle[y])
     70         {
     71             //yx=0;
     72             dfs(y,tt);
     73         }
     74         if(!cle[y])
     75         {
     76             yx=0;       
     77         }
     78     }
     79     cle[x]=yx&cle2[x];
     80 }
     81 int main(){
     82     scanf("%d%d%d",&n,&m,&t);
     83     for(int i=1;i<=n;i++)
     84         scanf("%d",&g[i]);
     85     for(int i=1;i<=m;i++)
     86         scanf("%d%d",&f[i][0],&f[i][1]);
     87     for(int i=1;i<=t;i++)
     88     {
     89         int x,y;
     90         scanf("%d%d",&x,&y);
     91         build(x,y,i);
     92         build(y,x,i);
     93     }
     94     for(int i=1;i<=n;i++)
     95         fa[i]=i;
     96     for(int i=1;i<=m;i++)
     97     {
     98         int from=f[i][0],to=f[i][1];
     99         dfs(from,to);
    100         while(!q1.empty())
    101         {
    102             ro tt=q1.top();
    103             q1.pop();
    104             int x=tt.from,y=tt.to;
    105             int p=min(g[x],g[y]);
    106             g[x]-=p;
    107             g[y]-=p;
    108             hav[to]+=p*2;
    109             if(!g[x]) cle2[x]=1;
    110             if(!g[y]) cle2[y]=1;
    111         }
    112         hb(from,to);
    113     }
    114     long long sum=0;
    115     for(int i=1;i<=n;i++)
    116     {
    117         if(find(i)==i)
    118         {
    119             sum+=hav[i];
    120         }
    121     }
    122     printf("%lld
    ",sum);
    123     //while(1);
    124     return 0;
    125 }
    暴力
     下面我来说一下我的正解。 
     貌似他们说正解是一个叫做克鲁斯卡尔重构树的东西,不过我不会,于是乎借鉴了一下思想乱搞出一下时间复杂度不是玄学的东西。
     首先如果我们假设每两个瓶子倒在一起之后都被扔掉,然后我们重新找一个瓶子装一下,那么我们就可以发现整个就是一个完美二叉树树林,能反应的两瓶药品如果反应一定是在他们的LCA上于是我们求一下离线LCA(之所以不用倍增是因为炸内存)。然后利用一个邻接表存一下发生在该节点的反应。然后按照他给的步骤去模拟设定一个now数组表示该药品实际在哪个节点,每合并一次就把合并后的节点的反应放进优先队列里面,处理一下就好了。
     
      1 #include<iostream>
      2 #include<cstdlib>
      3 #include<cstdio>
      4 #include<cstring>
      5 #include<queue>
      6 #include<algorithm>
      7 #include<cmath>
      8 #include<vector>
      9 #define N 1000005
     10 using namespace std;
     11 int n,m,t,zz;
     12 long long g[N];
     13 struct qu{
     14     int x,y;
     15     int next;
     16     int yxj;
     17     bool friend operator >(qu a,qu b)
     18     {
     19         return a.yxj>b.yxj;
     20     }
     21 }que[1000004];
     22 struct ro{
     23     int to,next,l;
     24 }road[1000005];
     25 int b[N*2],zz3;
     26 void bui(int x,int y){
     27     zz3++;
     28     road[zz3].to=y;
     29     road[zz3].next=b[x];
     30     b[x]=zz3;
     31 }
     32 struct no{
     33     int son[2],bh,fa;
     34     long long hav;
     35 }node[N*2];
     36 int zz2,now[N],a[N],fa[N],f2[N];
     37 void build(int x,int y,int z)
     38 {
     39     zz2++;
     40     que[zz2].x=x,que[zz2].y=y;
     41     que[zz2].yxj=z;
     42     que[zz2].next=a[x];
     43     a[x]=zz2;
     44 }
     45 int find(int x)
     46 {
     47     if(fa[x]==x)return x;
     48     else return fa[x]=find(fa[x]);
     49 }
     50 void hb(int x,int y)
     51 {
     52     int aa=find(x),bb=find(y);
     53     if(aa!=bb)
     54         fa[aa]=bb;
     55 }
     56 bool vis[N];
     57 void work(int x)
     58 {
     59     f2[x]=x;
     60     vis[x]=1;
     61     if(node[x].son[0])
     62     {
     63         work(node[x].son[0]);
     64         hb(x,node[x].son[0]);
     65         f2[find(x)]=x;
     66          
     67         work(node[x].son[1]);
     68         hb(x,node[x].son[1]);
     69         f2[find(x)]=x;
     70     }
     71     for(int i=a[x];i>0;i=que[i].next)
     72     {
     73         int y=que[i].y;
     74         if(vis[y])
     75         {
     76             bui(f2[find(y)],i);
     77         }
     78     }
     79 }
     80 priority_queue<qu,vector<qu>,greater<qu > > q1;
     81 int f[N][2];
     82 int main(){
     83     scanf("%d%d%d",&n,&m,&t);
     84     zz=n;
     85     for(int i=1;i<=n;i++) node[i].bh=i,now[i]=i;
     86     for(int i=1;i<=n;i++)
     87         scanf("%lld",&g[i]);
     88     for(int i=1;i<=m;i++)
     89     {
     90         int x,y;
     91         scanf("%d%d",&x,&y);
     92         zz++;
     93         node[now[x]].fa=node[now[y]].fa=zz;
     94         node[zz].bh=y;
     95         node[zz].son[0]=now[x],node[zz].son[1]=now[y];
     96         now[y]=zz;
     97         f[i][0]=x,f[i][1]=y;
     98     }
     99     for(int i=1;i<=zz;i++)
    100         fa[i]=i;
    101     for(int i=1;i<=t;i++)
    102     {
    103         int x,y;
    104         scanf("%d%d",&x,&y);
    105         build(x,y,i);
    106         build(y,x,i);
    107     }
    108  
    109     for(int i=1;i<=zz;i++)
    110     {
    111         if(!node[i].fa)
    112         {
    113             memset(vis,0,sizeof(vis));
    114             work(i);
    115         }
    116         if(i<=n)
    117             now[i]=i;
    118     }
    119     long long ans=0;
    120     for(int i=1;i<=m;i++)
    121     {
    122         int from=f[i][0],to=f[i][1];
    123         int x=now[from],y=now[to];
    124         int ff=node[x].fa;
    125         for(int j=b[ff];j>0;j=road[j].next)
    126             q1.push(que[road[j].to]);
    127         while(!q1.empty())
    128         {
    129             qu aa=q1.top();
    130             int p=min(g[aa.x],g[aa.y]);
    131             g[aa.x]-=p;
    132             g[aa.y]-=p;
    133             node[ff].hav+=2*p;
    134             q1.pop();
    135         }
    136         node[ff].hav+=node[y].hav+node[x].hav;
    137         now[to]=ff;
    138     }
    139      
    140     for(int i=1;i<=zz;i++)
    141     {
    142         if(!node[i].fa)
    143         {
    144             ans+=node[i].hav;
    145         }
    146     }
    147     printf("%lld
    ",ans);
    148     //while(1);
    149     return 0;
    150 }
    LCA做法
     
  • 相关阅读:
    UISegmentControl
    UISwitch 开关控件
    UI弹出键盘和收回键盘
    UITextField的属性设置
    UIButton的属性设置
    UILabel 的属性设置
    创建UIView对象
    id和instancetype的异同
    SPOJ FIBPOL
    HDU 6168 Numbers
  • 原文地址:https://www.cnblogs.com/liutianrui/p/7470086.html
Copyright © 2011-2022 走看看