POJ——T3417 Network

http://poj.org/problem?id=3417

Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 5294   Accepted: 1517

Description

Yixght is a manager of the company called SzqNetwork(SN). Now she's very worried because she has just received a bad news which denotes that DxtNetwork(DN), the SN's business rival, intents to attack the network of SN. More unfortunately, the original network of SN is so weak that we can just treat it as a tree. Formally, there are N nodes in SN's network, N-1 bidirectional channels to connect the nodes, and there always exists a route from any node to another. In order to protect the network from the attack, Yixght builds M new bidirectional channels between some of the nodes.

As the DN's best hacker, you can exactly destory two channels, one in the original network and the other among the M new channels. Now your higher-up wants to know how many ways you can divide the network of SN into at least two parts.

Input

The first line of the input file contains two integers: N (1 ≤ N ≤ 100 000), M (1 ≤ M ≤ 100 000) — the number of the nodes and the number of the new channels.

Following N-1 lines represent the channels in the original network of SN, each pair (a,b) denote that there is a channel between node a and node b.

Following M lines represent the new channels in the network, each pair (a,b) denote that a new channel between node a and node b is added to the network of SN.

Output

Output a single integer — the number of ways to divide the network into at least two parts.

Sample Input

4 1
1 2
2 3
1 4
3 4

Sample Output

3

Source

 
 
n-1条边构成的树,m条边中每加一条比构成环,假设新边为(u,v),那么环为u->LCA(u,v)->v->u,我们给这个环上的边计数1,表示这些边被一个环覆盖了一次。
可以发现

1.覆盖0次,说明这条边不在任何一个环上,这样的边最脆弱,单单是毁掉它就已经可以使树断裂了,这时候只要任意选一条新边去毁,树还是断裂的,所以这样的树边,就产生m种方案(m为新边条数)

2.覆盖1次,说明这条边在一个环上,且,仅在一个环上,那么要使树断裂,就毁掉这条树边,并且毁掉和它对应的那条新边(毁其他的新边无效),就一定能使树断裂,这种树边能产生的方案数为1,一条这样的树边只有唯一解

3.覆盖2次或以上,无论怎么样都不能使树断裂,产生的方案数为0

树上查分维护覆盖次数,树剖求得lca

 1 #include <cstdio>
 2 
 3 #define swap(a,b) {int tmp=a;a=b;b=tmp;}
 4 inline void read(int &x)
 5 {
 6     x=0; register char ch=getchar();
 7     for(; ch>'9'||ch<'0'; ) ch=getchar();
 8     for(; ch>='0'&&ch<='9'; ch=getchar()) x=x*10+ch-'0';
 9 }
10 
11 const int N(100005);
12 int head[N],sumedge;
13 struct Edge {
14     int v,next;
15     Edge(int v=0,int next=0):v(v),next(next){}
16 }edge[N<<2];
17 inline void ins(int u,int v)
18 {
19     edge[++sumedge]=Edge(v,head[u]); head[u]=sumedge;
20     edge[++sumedge]=Edge(u,head[v]); head[v]=sumedge;
21 }
22 
23 int top[N],size[N],dep[N],son[N],dad[N];
24 void DFS(int u,int depth)
25 {
26     size[u]=1,dep[u]=depth;
27     for(int v,i=head[u]; i; i=edge[i].next)
28     {
29         v=edge[i].v;
30         if(v==dad[u]) continue;
31         dad[v]=u; DFS(v,depth+1); size[u]+=size[v];
32         if(size[son[u]]<size[v])  son[u]=v;
33     }
34 }
35 void DFS_(int u,int Top)
36 {
37     top[u]=Top;
38     if(son[u]) DFS_(son[u],Top);
39     for(int v,i=head[u]; i; i=edge[i].next)
40     {
41         v=edge[i].v;
42         if(v!=dad[u]&&v!=son[u]) DFS_(v,v);
43     }
44 }
45 inline int LCA(int x,int y)
46 {
47     for(; top[x]!=top[y]; x=dad[top[x]])
48         if(dep[top[x]]<dep[top[y]]) swap(x,y);
49     return dep[x]<dep[y]?x:y;
50 }
51 
52 long long val[N],ans;
53 void DFSVAL(int u)
54 {
55     for(int i=head[u]; i; i=edge[i].next)
56         if(edge[i].v!=dad[u]) DFSVAL(edge[i].v),val[u]+=val[edge[i].v];
57 }
58 
59 int Presist()
60 {
61     int n,m; read(n),read(m);
62     for(int u,v,i=1; i<n; ++i)
63         read(u),read(v),ins(u,v);
64     DFS(1,0); DFS_(1,1);
65     for(int lca,u,v,i=1; i<=m; ++i)
66     {
67         read(u),read(v);
68         lca=LCA(u,v);
69         val[u]++,val[v]++;
70         val[lca]-=2;
71     }
72     DFSVAL(1);
73     for(int i=2; i<=n; ++i)
74         if(val[i]==1) ans++;
75         else if(!val[i]) ans+=m;
76     printf("%lld
",ans);
77     return 0;
78 }
79 
80 int Aptal=Presist();
81 int main(int argc,char*argv[]){;}
——每当你想要放弃的时候,就想想是为了什么才一路坚持到现在。
原文地址:https://www.cnblogs.com/Shy-key/p/7599161.html