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
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\n",ans); 77 return 0; 78 } 79 80 int Aptal=Presist(); 81 int main(int argc,char*argv[]){;}