zoukankan      html  css  js  c++  java
  • [补档][COGS 2434]暗之链锁

    [COGS 2434]暗之链锁

    题目

    传说中的暗之连锁被人们称为Dark。<!--more-->Dark是人类内心的黑暗的产物,古今中外的勇者们都试图打倒它。经过研究,你发现Dark呈现无向图的结构,图中有N个节点和两类边,一类边被称为主要边,而另一类被称为附加边。Dark有N – 1条主要边,并且Dark的任意两个节点之间都存在一条只由主要边构成的路径。另外,Dark还有M条附加边。
    你的任务是把Dark斩为不连通的两部分。一开始Dark的附加边都处于无敌状态,你只能选择一条主要边切断。一旦你切断了一条主要边,Dark就会进入防御模式,主要边会变为无敌的而附加边可以被切断。但是你的能力只能再切断Dark的一条附加边。现在你想要知道,一共有多少种方案可以击败Dark。
    注意,就算你第一步切断主要边之后就已经把Dark斩为两截,你也需要切断一条附加边才算击败了Dark。

    INPUT

    第一行包含两个整数N和M。
    之后N – 1行,每行包括两个整数A和B,表示A和B之间有一条主要边。
    之后M行以同样的格式给出附加边。

    OUTPUT

    输出一个整数表示答案。

    SAMPLE

    INPUT

    4 1
    1 2
    2 3
    1 4
    3 4

    OUTPUT

    3

    解题报告

    第一眼看这题,还以为要用每个点的度来做= =
    正经的解法:
    求出每条正经的边被多少条附加边(不正经的边?(雾))所覆盖,设其为x
    然后对每一条正经的边询问,只有x==0||x==1时,这条边才能被砍(正确性显然,因为如果x>1,你就算砍了它,再砍一条覆盖它的附加边,也没啥用,无法使其不连通)
    当x==0时,m条边随便砍,故对答案的贡献为m
    当x==1时,只有砍了覆盖它的那条附加边才有用,故对答案的贡献为1

    那么问题来了,咋求这个x呢?
    显然正经的边形成的是一棵树,那么我们就可以将边权下放到点权(为啥?好算啊= =),这样除了根,每个点都会有点权值,我们就可以用差分的思想来解决这个问题,dfs序跑一遍,修改时LCA-2,两端点+1(想想为什么?差分这东西,就是靠正负的抵消与修改后对区间和的影响来搞的,这样做的目的也就很明显了),那么该点权值自然就为从dfs序左端点到右端点的区间和。剩下的就十分简单了,乱搞出奇迹= =
     
      1 #include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 using namespace std;
      5 inline int read(){
      6     int sum(0);
      7     char ch(getchar());
      8     while(ch<'0'||ch>'9')
      9         ch=getchar();
     10     while(ch>='0'&&ch<='9'){
     11         sum=sum*10+ch-'0';
     12         ch=getchar();
     13     }
     14     return sum;
     15 }
     16 int n,m;
     17 struct edge{
     18     int s,e,n;
     19 }a[200001];
     20 int pre[100001],tot;
     21 inline void insert(int s,int e){
     22     a[++tot].s=s;
     23     a[tot].e=e;
     24     a[tot].n=pre[s];
     25     pre[s]=tot;
     26 }
     27 int fa[100001],dep[100001],size[100001],son[100001];
     28 inline void dfs1(int u){
     29     son[u]=0;
     30     for(int i=pre[u];i!=-1;i=a[i].n){
     31         int e(a[i].e);
     32         if(e!=fa[u]){
     33             fa[e]=u;
     34             dep[e]=dep[u]+1;
     35             dfs1(e);
     36             size[u]+=size[e];
     37             if(size[e]>size[son[u]])
     38                 son[u]=0;
     39         }
     40     }
     41 }
     42 int cnt;
     43 int r[100001];
     44 int top[100001],id[100001],pos[100001];
     45 inline void dfs2(int u,int rt){
     46     top[u]=rt;
     47     id[u]=++cnt;
     48     pos[cnt]=u;
     49     if(son[u])
     50         dfs2(son[u],rt);
     51     for(int i=pre[u];i!=-1;i=a[i].n){
     52         int e(a[i].e);
     53         if(e!=fa[u]&&e!=son[u])
     54             dfs2(e,e);
     55     }
     56     r[u]=cnt;
     57 }
     58 int sum[100001];
     59 inline int lowbit(int x){
     60     return x&-x;
     61 }
     62 inline void update(int pos,int c){
     63     while(pos<=n){
     64         sum[pos]+=c;
     65         pos+=lowbit(pos);
     66     }
     67 }
     68 inline int su(int pos){
     69     int ret(0);
     70     while(pos){
     71         ret+=sum[pos];
     72         pos-=lowbit(pos);
     73     }
     74     return ret;
     75 }
     76 inline int query(int l,int r){
     77     return su(r)-su(l-1);
     78 }
     79 inline void swp(int &a,int &b){
     80     a^=b;
     81     b^=a;
     82     a^=b;
     83 }
     84 inline int LCA(int x,int y){
     85     while(top[x]^top[y]){
     86         if(dep[top[x]]<dep[top[y]])
     87             swp(x,y);
     88         x=fa[top[x]];
     89     }
     90     return dep[x]<dep[y]?x:y;
     91 }
     92 inline void change(int x,int y){
     93     int lca(LCA(x,y));
     94     update(id[lca],-2);
     95     update(id[x],1);
     96     update(id[y],1);
     97 }
     98 inline int Q(int x){
     99     return query(id[x],r[x]);
    100 }
    101 typedef long long L;
    102 L ans(0);
    103 inline L get(int x){
    104     if(x==0)
    105         return m;
    106     if(x==1)
    107         return 1;
    108     else
    109         return 0;
    110 }
    111 inline int gg(){
    112     freopen("yam.in","r",stdin);
    113     freopen("yam.out","w",stdout);
    114     memset(pre,-1,sizeof(pre));
    115     n=read(),m=read();
    116     for(int i=1;i<n;i++){
    117         int x(read()),y(read());
    118         insert(x,y);
    119         insert(y,x);
    120     }
    121     dfs1(1);
    122     dfs2(1,1);
    123     for(int i=1;i<=m;i++){
    124         int x(read()),y(read());
    125         change(x,y);
    126     }
    127     for(int i=2;i<=n;i++){
    128         int ret(Q(i));
    129         ans+=get(ret);
    130     }
    131     printf("%d",ans);
    132 }
    133 int K(gg());
    134 int main(){;}
    View Code
    ps:树状数组比线段树lazy快一万倍= =
  • 相关阅读:
    Linux 的文件软链接如何删除
    mysql-xtrabackup备份sh: xtrabackup_56: command not found与error while loading shared libraries: libssl.so.6: cannot open shared object file: No such file or directory
    How To Upgrade ASMLib Kernel Driver as Part of Kernel Upgrade? (文档 ID 1391807.1)
    [trouble] error connecting to master 'repl@192.168.1.107:3306'
    Troubleshooting 10g and 11.1 Clusterware Reboots (文档 ID 265769.1)
    "Last_IO_Error: Fatal error: The slave I/O thread stops because master and slave have equal MySQL server UUIDs
    RMAN-06900 RMAN-06901 ORA-19921
    一则ORACLE进程都在但是无法进入实例的问题
    VirtualBox下Win7下CPU高占用的一次故障解决
    netcore之mysql中文乱码问题解决记录
  • 原文地址:https://www.cnblogs.com/hzoi-mafia/p/7276822.html
Copyright © 2011-2022 走看看