1553:【例 2】暗的连锁
1553:【例 2】暗的连锁
【题目描述】
原题来自:POJ 3417
Dark 是一张无向图,图中有 NN 个节点和两类边,一类边被称为主要边,而另一类被称为附加边。Dark 有 N–1N–1 条主要边,并且 Dark 的任意两个节点之间都存在一条只由主要边构成的路径。另外,Dark 还有 MM 条附加边。
你的任务是把 Dark 斩为不连通的两部分。一开始 Dark 的附加边都处于无敌状态,你只能选择一条主要边切断。一旦你切断了一条主要边,Dark 就会进入防御模式,主要边会变为无敌的而附加边可以被切断。但是你的能力只能再切断 Dark 的一条附加边。
现在你想要知道,一共有多少种方案可以击败 Dark。注意,就算你第一步切断主要边之后就已经把 Dark 斩为两截,你也需要切断一条附加边才算击败了 Dark。
【输入】
第一行包含两个整数 NN 和 MM;
之后 N–1N–1行,每行包括两个整数 AA 和 BB,表示 AA 和 BB 之间有一条主要边;
之后 MM 行以同样的格式给出附加边。
【输出】
输出一个整数表示答案。
【输入样例】
4 1 1 2 2 3 1 4 3 4
【输出样例】
3
【提示】
数据范围与提示:
对于 20% 的数据,1≤N,M≤1001≤N,M≤100;
对于 100% 的数据,1≤N≤105,1≤M≤2×1051≤N≤105,1≤M≤2×105 。数据保证答案不超过 231−1231−1。
![]() |
#include<iostream>
using namespace std;
const int mxn=1e5+5;
int n,m;
int f[mxn][30],w[mxn*5],d[mxn];
struct vec{
int nxt,to;
}g[2*mxn];
int first[mxn],len;
void add(int x,int y){
g[++len].to=y;
g[len].nxt=first[x];
first[x]=len;
}
void pre(int u,int fa){
d[u]=d[fa]+1;
for(int i=1;i<=19;i++){
f[u][i]=f[f[u][i-1]][i-1];
}
for(int i=first[u];i;i=g[i].nxt){
int v=g[i].to;
if(v!=fa){
f[v][0]=u;
pre(v,u);
}
}
}
int lca(int x,int y){
if(d[x]<d[y]){
swap(x,y);
}
for(int i=19;i>=0;i--){
if(d[f[x][i]]>=d[y]){
x=f[x][i];
}
if(x==y){
return x;
}
}
for(int i=19;i>=0;i--){
if(f[x][i]!=f[y][i]){
x=f[x][i];
y=f[y][i];
}
}
return f[x][0];
}
void dfs(int u,int fa){
for(int i=first[u];i;i=g[i].nxt |