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快一万倍= =
  • 相关阅读:
    【达梦公开课】视频汇总
    【.NET框架】—— MVC5+EF6实体——连表视图查询(七)
    【.NET框架】—— MVC5+EF6实体模型自动创建(七)
    【.NET框架】—— MVC5+EF进行CRUD(六)
    SqlServer必知必会之个人小笔记
    【.NET框架】—— ASP.NET MVC5路由基础(五)
    【.NET框架】—— MVC5 与jQuery库(四)
    【.NET框架】—— ASP.NET MVC数据验证注解(三)
    面试时写不出排序算法?看这篇就够了——转载《java那些事》微信公众号
    【.NET框架】—— ASP.NET MVC5 表单和HTML辅助(二)
  • 原文地址:https://www.cnblogs.com/hzoi-mafia/p/7276822.html
Copyright © 2011-2022 走看看