【tarjan】【樹的直徑】【CF】K. Königsberg Bridges
阿新 • • 發佈:2021-11-13
【tarjan】【樹的直徑】【CF】K. Königsberg Bridges
#include <bits/stdc++.h> #define MEM(a,x) memset(a,x,sizeof(a)) #define W(a) while(a) #define gcd(a,b) __gcd(a,b) #define pi acos(-1.0) #define PII pair<int,int> #define pb push_back #define mp make_pair #define fi first #define se second #define ll long long #define ull unsigned long long #define rep(i,x,n) for(int i=x;i<n;i++) #define repd(i,x,n) for(int i=x;i<=n;i++) #define MAX 1000005 #define MOD 1000000007 #define INF 0x3f3f3f3f #define lowbit(x) (x&-x) #define de(x) cout<<"debug : "<<x<<endl using namespace std; inline int read() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); } while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar(); return x*f; } const int N = 1E6+100, M = 2E6+100; struct edge{ int u,v,nxt; }edges[M],edges_scc[M]; int idx,h[N]; void add_edge(int u,int v) { edges[idx] = {u,v,h[u]}; h[u] = idx++; } int idx_scc,h_scc[N]; void add_scc(int u,int v) { edges_scc[idx_scc] = {u,v,h_scc[u]}; h_scc[u] = idx_scc++; } int low[N],dfn[N],time_stamp,scc_cnt,bel[N]; bool in_st[N],is_bridge[M]; stack<int > st; vector<int > scc[N]; void tarjan(int u,int from) { dfn[u] = low[u] = ++time_stamp; in_st[u] = true; st.push(u); for(int i = h[u];~i;i=edges[i].nxt) { int v = edges[i].v; if(!dfn[v]) { tarjan(v,i); low[u] = min(low[v],low[u]); if(dfn[u]<low[v]) is_bridge[i] = is_bridge[i^1] = 1; } else if(i!=(from^1)) low[u] = min(low[v],low[u]); } if(dfn[u]==low[u]) { int t; do{ t = st.top(); st.pop(); in_st[t] = false; scc[scc_cnt].push_back(t); bel[t] = scc_cnt; }while(t!=u); scc_cnt++; } } int max_len,max_v; bool used[N]; void dfs(int u,int fa,int dep) { used[u] = true; if(dep>max_len) { max_v = u; max_len = dep; } for(int i = h_scc[u];~i;i=edges_scc[i].nxt) { if(edges_scc[i].v==fa) continue; dfs(edges_scc[i].v,u,dep+1); } } int main() { int n = read(),m = read(); memset(h,-1,sizeof(h)); memset(h_scc,-1,sizeof(h_scc)); for(int i=0;i<m;i++) { int u = read(),v = read(); add_edge(u,v);add_edge(v,u); } for(int i=0;i<n;i++) if(!dfn[i]) tarjan(i,-1); for(int i=0;i<idx;i+=2) if(is_bridge[i]) add_scc( bel[edges[i].u], bel[edges[i].v] ),add_scc( bel[edges[i].v],bel[edges[i].u]); int ans = 0,blocks = 0; for(int i=0;i<scc_cnt;i++) { if(!used[i]) { blocks ++; max_len = 0,max_v = i;//直徑的點要初始化好,不然還是停留在上一輪 dfs(i,-1,0); max_len = 0; dfs(max_v,-1,0); ans += max_len; } } cout<<ans+blocks-1; return 0; }