题意:
一个无向图 现要加一条边 使得所有桥的边权的最小值最大
思路:
首先做边双连通 然后缩点 因为双连通分量里不可能有桥 缩点后图变成了树
把这棵树建起来 再利用树形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; }
HDU 4005 The war,布布扣,bubuko.com
原文地址:http://blog.csdn.net/houserabbit/article/details/36628293