To irrigate the wilderness that's still asleep
怎么还有第二关。
设一条边被经过的次数为 \(d_i\)。则答案的最大值显然是 \(\sum min(d_i,2)\)。尝试通过构造达到这个最大值。
不妨考虑一点更加严格的限制:我们希望这条边正着经过和反着经过的次数差 \(\le 1\)。而我们很快就 \(recall\) 欧拉回路:如果图有欧拉回路,则对于割 \((A,B)\),满足离开 \(A\) 的次数等于回到 \(A\) 的次数。这个性质,几乎是完美契合这道题了。
但是问题是,我们如何进行建图呢?不难意识到,这题的“路径”是一个很重要的点。连 \((s_i,t_i)\) 因此是一个可行的想法。而我们同样还可以这样想:我们考虑割 \((S,V-S)\),其中 \(S\) 是一棵完整子树,其根为 \(u\),那么对于 \(fa_u\) 连向 \(u\) 的边,就是从 \(S\) 出去的路径 和 从 \(V-S\) 回来的路径啊。那我不直接只对着 \((s_i,t_i)\) 建边就好了?
但是显然我们不一定能构成欧拉回路,考虑直接贷一条边,那么我们自然是直接贷树边的,不难发现这样子我们最多会多算一次,和我们的理念契合。
Code
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false);cin.tie(0),cout.tie(0)
#define File(s) freopen(s".in","r",stdin);freopen(s".out","w",stdout)
#define LL long long
#define fi first
#define se second
const int N = 4e3 + 10;
int n,m;
vector<int> G[N];
vector<int> E[N];
int eu[N],ev[N],used[N],f[N],cnt,deg[N];
int s[N],t[N];
void add(int u,int v,int w){
cnt ++ ;
eu[cnt] = u,ev[cnt] = v,f[cnt] = w;
deg[u] ++ ;deg[v] ++ ;
E[u].push_back(cnt);E[v].push_back(cnt);
}
int fa[N],siz[N],dfn[N],idfn[N],son[N],top[N],dep[N],tot;
void dfs(int u,int rt){
fa[u] = rt;
siz[u] = 1;
dep[u] = dep[rt] + 1;
for(int v : G[u]){
if(v == rt) continue;
dfs(v,u);
if(siz[v] > siz[son[u]]) son[u] = v;
siz[u] += siz[v];
}
return ;
}
void dfs2(int u,int tp){
dfn[u] = ++tot;idfn[tot] = u;
top[u] = tp;
if(son[u]) dfs2(son[u],tp);
for(int v : G[u]){
if(v == fa[u] || v == son[u]) continue;
dfs2(v,v);
}
}
int LCA(int u,int v){
while(top[u] != top[v]){
if(dep[top[u]] > dep[top[v]]) swap(u,v);
v = fa[top[v]];
}
return (dep[u] < dep[v]) ? u : v;
}
int d[N];
int ans = 0;
void init(int u){
for(int v : G[u]){
if(v == fa[u]) continue;
init(v);
d[u] += d[v];
}
ans += min(2,d[u]);
}
void solve(int u){
while(!E[u].empty()){
int i = E[u].back();
E[u].pop_back();
if(used[i]) continue;
used[i] = 1;
int v = eu[i] ^ ev[i] ^ u;
if(f[i])
if(u != s[f[i]]) swap(s[f[i]],t[f[i]]);
solve(v);
}
}
int main(){
IOS;
cin >> n >> m;
for(int i=1;i<n;i++){
int u,v;
cin >> u >> v;
G[u].push_back(v);
G[v].push_back(u);
}
dfs(1,0); dfs2(1,1);
for(int i=1;i<=m;i++){
cin >> s[i] >> t[i];
add(s[i],t[i],i);
d[s[i]] ++ ;
d[t[i]] ++ ;
d[LCA(s[i],t[i])] -= 2;
}
init(1);
for(int i=n;i>=1;i--){
int u = idfn[i];
if(deg[u] % 2 == 1)
add(fa[u],u,0);
}
for(int i=1;i<=n;i++)
solve(i);
cout << ans << "\n";
for(int i=1;i<=m;i++)
cout << s[i] << " " << t[i] << "\n";
return 0;
}

浙公网安备 33010602011771号