题目链接
思路:
圆方树学习中。。。树边还是那样处理,对于环的话这个可以知道一个点不会绕远路去另一点,所以应该和环的一半的距离以内的点取直径最大值,单调队列处理就行了。
#include<bits/stdc++.h>
typedef long long ll;
const int maxn = 2e5 + 10;
const int INF = 1e9 + 7;
using namespace std;
typedef pair<int, int> edge;
int n, m, T, kase = 1;
vector<int> G[maxn], bcc[maxn];
int dp[maxn], dfn[maxn], dfs_clock, tot;
int pre[maxn], bccno[maxn], bcc_cnt;
int s[maxn], que[maxn];
stack<edge> S;
vector<int> et[maxn];
int dfs(int u, int fa) {
int lowu = pre[u] = ++dfs_clock, child = 0;
for(int i = 0; i < G[u].size(); i++) {
int v = G[u][i];
edge e = edge(u, v);
if(!pre[v]) {
S.push(e); child++;
int lowv = dfs(v, u);
lowu = min(lowu, lowv);
if(lowv >= pre[u]) {
bcc_cnt++; bcc[bcc_cnt].clear();
while(1) {
edge x = S.top(); S.pop();
if(bccno[x.second] != bcc_cnt) { bcc[bcc_cnt].push_back(x.second); bccno[x.second] = bcc_cnt; }
if(bccno[x.first] != bcc_cnt) { bcc[bcc_cnt].push_back(x.first); bccno[x.first] = bcc_cnt; }
if(x.first == u && x.second == v) break;
}
//cout << "bcc_cnt = " << bcc_cnt << endl;
// for(int j = 0; j < bcc[bcc_cnt].size(); j++) cout << bcc[bcc_cnt][j] << " "; cout << endl;
if(bcc[bcc_cnt].size() == 2) {
et[u].push_back(v); //树边
et[v].push_back(u);
} else {
//环边
tot++;
for(int i = 0; i < bcc[bcc_cnt].size(); i++) {
int v = bcc[bcc_cnt][i];
et[v].push_back(tot);
et[tot].push_back(v);
}
}
}
} else if(pre[v] < pre[u] && v != fa) {
S.push(e); lowu = min(lowu, pre[v]);
}
}
return lowu;
}
int ans;
void solve(int x, int fa) {
if(x <= n) {
dp[x] = 1;
for(int i = 0; i < et[x].size(); i++) {
if(et[x][i] == fa) continue;
solve(et[x][i], x);
if(et[x][i] <= n) {
ans = max(ans, dp[x] + dp[et[x][i]]);
dp[x] = max(dp[x], dp[et[x][i]] + 1);
}
}
ans = max(ans, dp[x]);
} else {
int len = et[x].size(); //len: 环的大小
for(int i = 0; i < et[x].size(); i++) {
int v = et[x][i]; if(v == fa) continue;
solve(v, x);
}
int l = 0, r = 0, cnt = 2 * len, sz = len / 2;
for(int i = 0; i < len; i++) s[i] = s[i + len] = et[x][i];
for(int i = 0; i < sz; i++) {
int k = dp[s[i]] - i;
while(r > l && dp[s[que[r - 1]]] - que[r - 1] <= k) r--;
que[r++] = i;
}
for(int i = sz; i < cnt; i++) {
int k = dp[s[i]] - i;
while(l < r && i - que[l] > sz) l++;
ans = max(ans, dp[s[i]] + i + dp[s[que[l]]] - que[l] - 1);
while(r > l && dp[s[que[r - 1]]] - que[r - 1] <= k) r--;
que[r++] = i;
}
for(int i = 0; i < et[x].size(); i++) {
int v = et[x][i]; if(v == fa) continue;
dp[fa] = max(dp[fa], dp[v] + min(i, len - i));
}
}
}
int main() {
ios::sync_with_stdio(0);
cin >> n >> m;
for(int i = 1; i <= m; i++) {
int u, v, t; cin >> t;
cin >> u;
for(int j = 1; j < t; j++) {
cin >> v;
G[u].push_back(v);
G[v].push_back(u);
u = v;
}
}
tot = n;
dfs(1, -1); solve(1, -1);
cout << ans - 1 << endl;
return 0;
}
/*
12 2
12 1 2 3 4 5 6 7 8 9 10 11 1
2 1 12
*/