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
",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
",ed[i].w); return 0;
}
}
printf("-1
");
return 0;
}