显然要先双连通缩成一棵树。 然后对于树上的边才有答案。
对于一条边来说, 两侧的最大值分为mx1 , mx2 , 那么 u 一定是min(mx1, mx2), v 一定是 u + 1。
这个经过仔细分析一下就能得到, 然后按dfs序建个st表就好啦。
#include<bits/stdc++.h> #define LL long long #define LD long double #define ull unsigned long long #define fi first #define se second #define mk make_pair #define PLL pair<LL, LL> #define PLI pair<LL, int> #define PII pair<int, int> #define SZ(x) ((int)x.size()) #define ALL(x) (x).begin(), (x).end() #define fio ios::sync_with_stdio(false); cin.tie(0); using namespace std; const int N = 1e5 + 2; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9 + 7; const double eps = 1e-8; const double PI = acos(-1); template<class T, class S> inline void add(T &a, S b) {a += b; if(a >= mod) a -= mod;} template<class T, class S> inline void sub(T &a, S b) {a -= b; if(a < 0) a += mod;} template<class T, class S> inline bool chkmax(T &a, S b) {return a < b ? a = b, true : false;} template<class T, class S> inline bool chkmin(T &a, S b) {return a > b ? a = b, true : false;} mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); int n, m; vector<PII> G[N]; vector<PII> bG[N]; int stk[N], top; int dfn[N], low[N], belong[N], idx, cnt; int mx[N]; bool brige[N]; PII ans[N]; int in[N], ot[N]; int Log[N]; struct ST { int dp[N][20]; int ty; void build(int n, int b[], int _ty) { ty = _ty; for(int i = -(Log[0]=-1); i < N; i++) Log[i] = Log[i - 1] + ((i & (i - 1)) == 0); for(int i = 1; i <= n; i++) { dp[in[i]][0] = mx[i]; } for(int j = 1; j <= Log[n]; j++) for(int i = 1; i+(1<<j)-1 <= n; i++) dp[i][j] = max(dp[i][j-1], dp[i+(1<<(j-1))][j-1]); } inline int query(int x, int y) { if(x > y) return 0; int k = Log[y - x + 1]; return ty * max(dp[x][k], dp[y-(1<<k)+1][k]); } } rmq; void tarjan(int u, int pid) { dfn[u] = low[u] = ++idx; stk[++top] = u; for(auto &e : G[u]) { if(e.fi == pid) continue; if(!dfn[e.se]) { tarjan(e.se, e.fi); chkmin(low[u], low[e.se]); if(dfn[u] < low[e.se]) { brige[e.fi] = true; } } else { chkmin(low[u], dfn[e.se]); } } if(dfn[u] == low[u]) { cnt++; while(1) { int v = stk[top--]; belong[v] = cnt; chkmax(mx[cnt], v); if(v == u) break; } } } void go(int u, int fa) { in[u] = ++idx; for(auto &e : bG[u]) { if(e.se == fa) continue; go(e.se, u); } ot[u] = idx; } void solve(int u, int fa) { for(auto &e : bG[u]) { int v = e.se, eid = e.fi; if(v == fa) continue; int mx1 = rmq.query(in[v], ot[v]); int mx2 = max(rmq.query(1, in[v] - 1), rmq.query(ot[v] + 1, cnt)); ans[eid].fi = min(mx1, mx2); ans[eid].se = ans[eid].fi + 1; solve(v, u); } } int main() { int T; scanf("%d", &T); while(T--) { scanf("%d%d", &n, &m); idx = cnt = top = 0; for(int i = 1; i <= n; i++) { G[i].clear(); bG[i].clear(); dfn[i] = low[i] = 0; mx[i] = 0; } for(int i = 1; i <= m; i++) { int u, v; scanf("%d%d", &u, &v); G[u].push_back(mk(i, v)); G[v].push_back(mk(i, u)); brige[i] = false; ans[i] = mk(0, 0); } for(int i = 1; i <= n; i++) { if(!dfn[i]) { tarjan(i, 0); } } for(int u = 1; u <= n; u++) { for(auto &e : G[u]) { if(belong[u] == belong[e.se]) continue; bG[belong[u]].push_back(mk(e.fi, belong[e.se])); } } idx = 0; go(1, 0); rmq.build(cnt, mx, 1); solve(1, 0); for(int i = 1; i <= m; i++) { printf("%d %d ", ans[i].fi, ans[i].se); } } return 0; } /* */