Luogu5234[JSOI2012]越獄老虎橋
阿新 • • 發佈:2019-03-15
void sort eof ger enable per 邊雙連通分量 mem ems
Luogu5234[JSOI2012]越獄老虎橋
題面:洛谷
解析
題意中的要求即為割掉權值最小的割邊,所以先把圖縮點(這裏應該是邊雙連通分量),現在考慮增加一條邊會對縮點後的樹造成什麽影響,無非是成環,然後環上的邊不能割掉。現在考慮貪心,從小到大加邊,若這些邊在一條鏈上,就繼續,反之輸出答案,用\(lca\)維護即可,註意特判。
代碼
// luogu-judger-enable-o2 #include<bits/stdc++.h> #define N 500005 #define M 1000005 using namespace std; int n,m; #define gc() getchar() inline int In(){ char c=gc(); int x=0,ft=1; for(;c<'0'||c>'9';c=gc()) if(c=='-') ft=-1; for(;c>='0'&&c<='9';c=gc()) x=x*10+c-'0'; return x*ft; } inline int min(int a,int b){ return a<b?a:b; } int h[N],U[M],V[M],W[M],e_tot=1; struct E{ int to,nex,d; }e[M<<1]; inline void add(int u,int v,int w){ e[++e_tot]=(E){v,h[u],w}; h[u]=e_tot; e[++e_tot]=(E){u,h[v],w}; h[v]=e_tot; } int dfs_clock=0,ecc_cnt=0,S_top=0,dfn[N],low[N],S[N],id[N]; void dfs(int u,int pre){ dfn[u]=low[u]=++dfs_clock; S[++S_top]=u; for(int i=h[u],v;i;i=e[i].nex){ v=e[i].to; if(v==pre) continue; if(!dfn[v]){ dfs(v,u); low[u]=min(low[u],low[v]); } else low[u]=min(low[u],dfn[v]); } if(dfn[u]==low[u]){ ++ecc_cnt; int v; do{ v=S[S_top--]; id[v]=ecc_cnt; }while(v!=u); } } int ec=0; struct Ed{ int u,v,w; bool operator < (const Ed& rhs) const { return w<rhs.w; } }ed[N]; int d[N],sz[N],son[N],fa[N],top[N]; void dfs1(int u,int pre,int dep){ d[u]=dep; fa[u]=pre; sz[u]=1; for(int i=h[u],v;i;i=e[i].nex){ v=e[i].to; if(v==fa[u]) continue; dfs1(v,u,dep+1); sz[u]+=sz[v]; if(!son[u]||sz[son[u]]<sz[v]) son[u]=v; } } void dfs2(int u,int pre){ top[u]=pre; if(son[u]) dfs2(son[u],pre); for(int i=h[u],v;i;i=e[i].nex){ v=e[i].to; if(v!=fa[u]&&v!=son[u]) dfs2(v,v); } } inline int LCA(int x,int y){ while(top[x]!=top[y]){ if(d[top[x]]<d[top[y]]) swap(x,y); x=fa[top[x]]; } return d[x]>d[y]?y:x; } int main(){ n=In(); m=In(); for(int i=1;i<=m;++i){ U[i]=In(); V[i]=In(); W[i]=In(); add(U[i],V[i],W[i]); } dfs(1,-1); e_tot=0; memset(h,0,sizeof(h)); for(int i=1;i<=m;++i){ U[i]=id[U[i]]; V[i]=id[V[i]]; if(U[i]!=V[i]){ add(U[i],V[i],W[i]); ed[++ec]=(Ed){U[i],V[i],W[i]}; } } dfs1(1,-1,0); dfs2(1,1); sort(ed+1,ed+1+ec); int a=ed[1].u,b=ed[1].v,pre=LCA(a,b); if(d[a]>d[b]) swap(a,b); for(int i=2,u,v;i<=ec;++i){ u=ed[i].u; v=ed[i].v; if(d[u]>d[v]) swap(u,v); int p1=LCA(u,a),p2=LCA(v,a),p3=LCA(u,b),p4=LCA(v,b); if(pre==a){ if(p1==a&&p2==a&&p3==u&&p4==v) continue; if(p3==b&&p4==b){ b=v; continue; } if(p1==u&&p2==v){ a=u; pre=a; continue; } if(d[p3]<=d[a]){ a=v; continue; } printf("%d\n",ed[i].w); return 0; } else{ if(p1==a&&p2==a){ a=v; continue; } if(p3==b&&p4==b){ b=v; continue; } if(d[u]>=d[pre]&&p1==u&&p2==v) continue; if(d[u]>=d[pre]&&p3==u&&p4==v) continue; printf("%d\n",ed[i].w); return 0; } } printf("-1\n"); return 0; }
Luogu5234[JSOI2012]越獄老虎橋