题目大意:
给定无根树,N个节点,N-1条树边,和M条“附加边”;
删除一条树边和一条附加边使图不再连通,求总方案数;
/*
*Network POJ3417
*/
#include <cstdio>
#include <cstdbool>
#include <cstring>
constexpr int NN{(int)(1e5)+1},MM{(int)(1e5)<<1|1};
using llong = long long;
int h[NN],ne[MM],to[MM],d[NN],s[NN],par[NN],tot = 0,LCA[NN][NN] = {0};
_Bool vst[NN];
inline void add(int u,int v){to[tot] = v,ne[tot] = h[u],h[u] = tot++;}
int find(int u){return par[u] == u?u:par[u] = find(par[u]);}
void init(int N){
memset(h,-1,sizeof h);tot = 0;memset(s,0,sizeof s);memset(d,0,sizeof d);
int i;for(i = 0;i <= N;++i)par[i] = i,LCA[1][i] = 1;
}
void tarjan(int u,int fa,int N){
int i;
for(i = h[u];~i;i = ne[i])if(!(to[i] == fa))tarjan(to[i],u,N),par[to[i]] = u,vst[to[i]];
for(i = 1;i <= N;++i)if(!vst[i])LCA[u][i] = find(i);
}
void dfs(int u,int fa){
s[u] = d[u];
int i;
for(i = h[i];~i;i = to[i])if(!(fa == to[i]))dfs(to[i],u),s[u]+=s[to[i]];
}
int main(void){
int N,M;
while(~scanf("%d%d",&N,&M) && (N || M)){
init(N);
int i,u,v;
for(i = N;i-->0;add(u,v),add(v,u))scanf("%d%d",&u,&v);
(void)tarjan(1,0,N);
while(M--){
scanf("%d%d",&u,&v);
++d[u],++d[v],d[LCA[u][v]] -= 2;
}
dfs(1,0);
llong ans = 0;
for(i = 1;i <= N;++i)ans += !(s[i] >= 1)?M:(size_t)(s[i] == 1);
printf("%lld\n",ans);
}
return 0;
}