【HDU5409】CRB and Graph 边双联通 子树最值
# 题意
有一个简单图,n个点,m条边。对于每条割边,求出删去这条边后,在两个联通块中各取一个u,v。使得u<v,并且u尽量大而v尽量小。
# 思路
求出边双联通是肯定的。
答案的限制条件是重点。
假设分出来的两个联通块,一个的最大值是mx1,另一个的最大值是mx2。那么u = min(mx1, mx2),因为取个小点的,才能在另一个联通块中找到对应的v。
显然mx1,mx2中一个值等于n,所以我们只用找不包含n的联通块中的最大值。
怎么找,可以令n为根结点,dfs子树的最大值就行了。
又由于v越小越好,我们可以直接令v = u + 1;
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <bits/stdc++.h> using namespace std; #define pb push_back #define fi first #define se second #define debug(x) cerr<<#x << " := " << x << endl; #define bug cerr<<"-----------------------"<<endl; #define FOR(a, b, c) for(int a = b; a <= c; ++ a) typedef long long ll; typedef long double ld; typedef pair<int, int> pii; typedef pair<ll, ll> pll; template<class T> void _R(T &x) { cin >> x; } void _R(int &x) { scanf("%d", &x); } void _R(ll &x) { scanf("%lld", &x); } void _R(double &x) { scanf("%lf", &x); } void _R(char &x) { scanf(" %c", &x); } void _R(char *x) { scanf("%s", x); } void R() {} template<class T, class... U> void R(T &head, U &... tail) { _R(head); R(tail...); } template<typename T> inline T read(T&x){ x=0;int f=0;char ch=getchar(); while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar(); while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x=f?-x:x; } const int inf = 0x3f3f3f3f; const int mod = 1e9+7; /**********showtime************/ const int maxn = 1e5+9; vector<pii>mp[maxn]; set <pii>nmp[maxn]; int dfn[maxn],low[maxn],belong[maxn],tim; int scc_cnt; int ans[maxn]; int a[maxn], dp[maxn]; stack<int>st; void dfs(int u, int fa) { dfn[u] = low[u] = ++tim; st.push(u); for(pii p : mp[u]){ int v = p.fi; if(v == fa) continue; if(!dfn[v]) dfs(v, u); if(!belong[v]) low[u] = min(low[u], low[v]); } if(low[u] == dfn[u]) { scc_cnt++; nmp[scc_cnt].clear(); int now; while(true){ now = st.top(); st.pop(); belong[now] = scc_cnt; a[scc_cnt] = max(a[scc_cnt], now); if(now == u) break; } } } void cal(int u, int fa) { dp[u] = a[u]; for(pii p : nmp[u]) { int v = p.fi, id = p.se; if(v == fa) continue; cal(v, u); ans[id] = dp[v]; dp[u] = max(dp[u], dp[v]); } } int main(){ int T; scanf("%d", &T); while(T--) { int n,m; scanf("%d%d", &n, &m); for(int i=1; i<=n; i++) mp[i].clear(), dfn[i] = 0,dp[i] = 0, a[i] = 0,belong[i] = 0; for(int i=1; i<=m; i++) { int u,v; scanf("%d%d", &u, &v); mp[u].pb(pii(v, i)); mp[v].pb(pii(u, i)); ans[i] = 0; } tim = 0; scc_cnt = 0; for(int i=1; i<=n; i++) if(!dfn[i]) dfs(i, i); for(int u=1; u<=n; u++) { for(pii p : mp[u]) { int v = p.fi; if(belong[u] == belong[v]) continue; nmp[belong[u]].insert(pii(belong[v], p.se)); } } cal(belong[n], belong[n]); for(int i=1; i<=m; i++) printf("%d %d\n", ans[i], ans[i] + (ans[i] != 0)); } return 0; }
skr