题意:
一个无向图 现要加一条边 使得所有桥的边权的最小值最大
思路:
首先做边双连通 然后缩点 因为双连通分量里不可能有桥 缩点后图变成了树
把这棵树建起来 再利用树形dp处理出答案 处理方法是 找到树中的最小边把它断开形成两棵树
现在就是要维护两棵树内各一条路径使得答案出现 易知路径的方向总是朝向子树中包含边权最小的方向
做出dp[i]表示以i为根的子树内的最小边权 之后路径就会出现 然后将不在路径上的dp取最小值即可
注意:
图和树的变量名尽量明显区别 (我就是因为变量名写错WA了几十次…
图如果不连通要直接输出-1 (这个明显就是题出的不好… 按道理讲应该输出所有边里最小值
整幅图就是一个双连通分量要特判 输出-1
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 10010
#define M 100010
#define inf 1000000
struct edge
{
int u,v,w,next,flag,bridge;
}ed[M*2];
struct tree
{
int u,v,w,next;
}te[M*2];
int head[N],dfn[N],low[N],belong[N],hte[N],dp[N],to[N];
int n,m,tot,idx,cnt,tol,ans;
void init()
{
for(int i=1;i<=n;i++)
{
head[i]=dfn[i]=hte[i]=-1;
belong[i]=to[i]=0;
dp[i]=inf;
}
tot=idx=cnt=tol=0;
ans=inf;
}
void add(int u,int v,int w)
{
ed[tot].u=u;
ed[tot].v=v;
ed[tot].w=w;
ed[tot].next=head[u];
head[u]=tot;
ed[tot].flag=0;
ed[tot].bridge=0;
tot++;
}
void tarjan(int u)
{
int i,v,num=0;
dfn[u]=low[u]=++idx;
for(i=head[u];~i;i=ed[i].next)
{
v=ed[i].v;
if(ed[i].flag) continue;
ed[i].flag=ed[i^1].flag=1;
if(dfn[v]==-1)
{
tarjan(v);
low[u]=min(low[u],low[v]);
if(dfn[u]<low[v])
{
ed[i].bridge=1;
ed[i^1].bridge=1;
}
}
else low[u]=min(low[u],dfn[v]);
}
}
bool solve()
{
int i;
tarjan(1);
for(i=1;i<=n;i++)
{
if(dfn[i]==-1) return false;
}
return true;
}
void color(int u)
{
int i;
belong[u]=cnt;
for(i=head[u];~i;i=ed[i].next)
{
if(ed[i].bridge) continue;
if(!belong[ed[i].v]) color(ed[i].v);
}
}
void addedge(int u,int v,int w)
{
te[tol].u=u;
te[tol].v=v;
te[tol].w=w;
te[tol].next=hte[u];
hte[u]=tol++;
}
int maketree()
{
int i,u,v,res=inf;
for(i=1;i<=n;i++)
{
if(!belong[i])
{
cnt++;
color(i);
}
}
for(i=0;i<tot;i+=2)
{
if(ed[i].bridge)
{
u=belong[ed[i].u];
v=belong[ed[i].v];
addedge(u,v,ed[i].w);
addedge(v,u,ed[i].w);
res=min(res,ed[i].w);
}
}
return res;
}
void makedp(int u,int fa)
{
int i,v,tmp;
for(i=hte[u];~i;i=te[i].next)
{
v=te[i].v;
if(v==fa) continue;
makedp(v,u);
tmp=min(dp[v],te[i].w);
if(dp[u]>tmp)
{
dp[u]=tmp;
to[u]=v;
}
}
}
void findans(int u,int fa)
{
int i,v,tmp;
for(i=hte[u];~i;i=te[i].next)
{
v=te[i].v;
if(v==fa||v==to[u]) continue;
tmp=min(dp[v],te[i].w);
ans=min(ans,tmp);
}
if(to[u]) findans(to[u],u);
}
int main()
{
int i,u,v,w,minw;
while(~scanf("%d%d",&n,&m))
{
init();
for(i=1;i<=m;i++)
{
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
add(v,u,w);
}
if(!solve())
{
puts("-1");
continue;
}
minw=maketree();
if(minw==inf)
{
puts("-1");
continue;
}
for(i=0;i<tol;i+=2)
{
if(te[i].w==minw)
{
makedp(te[i].u,te[i].v);
makedp(te[i].v,te[i].u);
findans(te[i].u,te[i].v);
findans(te[i].v,te[i].u);
break;
}
}
if(ans!=inf) printf("%d\n",ans);
else puts("-1");
}
return 0;
}