真正的危机不是机器人像人一样思考,而是人像机器一样思考。 ——凉宫春日的忧郁

[补档][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快一万倍= =
posted @ 2017-08-02 21:01  Hzoi_Mafia  阅读(252)  评论(0编辑  收藏  举报
我们都在命运之湖上荡舟划桨,波浪起伏着而我们无法逃脱孤航。但是假使我们迷失了方向,波浪将指引我们穿越另一天的曙光。 ——死神