暗之的锁链 [COGS2434] [树上差分]

Description

无向图中有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

Sample Output

3

Hint

对于20% 的数据,N≤100,M≤100。
对于100% 的数据,N≤100 000,M≤200 000。数据保证答案不超过2^31– 1。

Solution

对于一条附加边,可以对两点到它们的LCA之间的边产生影响

当一条主要边不受影响时,可以和任意一条附加边产生组合。

当一条主要边只受一条附加边影响时,可以与这一条附加边产生组合

当一条主要边受多条附加边影响时,删了这条主要边,仍有两条以上的边连接两边,够不成独立区域

故进行树上差分即可 (dfs序)

Code

 

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 #define RG register int
 6 #define rep(i,a,b)    for(RG i=a;i<=b;i++)
 7 #define per(i,a,b)    for(RG i=a;i>=b;i--)
 8 #define inf (1<<30)
 9 #define maxn 100005
10 #define maxm 200005
11 using namespace std;
12 int n,m,cnt,id,ans;
13 int head[maxn],cf[maxn];
14 int son[maxn],sz[maxn],fa[maxn],dep[maxn],dfn[maxn],top[maxn];
15 struct E{
16     int v,next;
17 }e[maxn<<1];
18 
19 inline int read()
20 {
21     int x=0,f=1;char c=getchar();
22     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
23     while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
24     return x*f;
25 }
26 
27 inline void add(int u,int v)
28 {
29     e[++cnt].v=v,e[cnt].next=head[u],head[u]=cnt;
30 }
31 
32 void dfs1(int u,int pa)
33 {
34     sz[u]=1,son[u]=0,fa[u]=pa,dep[u]=dep[pa]+1;
35     for(int i=head[u];i;i=e[i].next)
36     {
37         int v=e[i].v;
38         if(v==pa)    continue;
39         dfs1(v,u);
40         sz[u]+=sz[v];
41         if(sz[v]>sz[son[u]])son[u]=v;
42     }
43 }
44 
45 void dfs2(int u,int tp)
46 {
47     dfn[u]=++id,top[u]=tp;
48     if(!son[u])    return;
49     dfs2(son[u],tp);
50     for(int i=head[u];i;i=e[i].next)
51         if(e[i].v!=son[u]&&e[i].v!=fa[u])    dfs2(e[i].v,e[i].v);
52 
53 }
54 
55 int work(int x,int y)
56 {
57     while(top[x]!=top[y])
58     {
59         if(dep[top[x]]<dep[top[y]])    swap(x,y);
60         --cf[dfn[x]+1],++cf[dfn[top[x]]];
61         x=fa[top[x]];
62     }
63     if(dep[x]>dep[y])    swap(x,y);
64     ++cf[dfn[x]+1],--cf[dfn[y]+1];
65 }
66 
67 int main()
68 {
69     n=read(),m=read();
70     RG u,v;
71     rep(i,2,n)    u=read(),v=read(),add(u,v),add(v,u);
72     dfs1(1,0);
73     dfs2(1,0);
74     rep(i,1,m)
75     {
76         u=read(),v=read();
77         work(u,v);
78     }
79     rep(i,2,n)
80     {
81         cf[i]+=cf[i-1];
82         if(!cf[i])    ans+=m;
83         else if(cf[i]==1)    ans++;
84     }
85     printf("%d\n",ans);
86     return 0;
87 }
View Code

 

posted @ 2018-04-02 10:44  iBilllee  阅读(259)  评论(0编辑  收藏  举报