奉上数据:
6 7
1 2 1
2 1 1
2 3 1
3 4 1
4 3 1
1 6 2
4 5 3
5 8
1 2 1
2 1 1
2 3 2
3 2 2
3 4 3
4 3 3
4 5 4
5 4 4
1 0
7 7
1 2 1
2 4 2
3 4 1
4 3 1
3 5 2
3 6 3
6 7 3
缩点后的树边中,找出最小的边,从最小边的两端点出发,分别含有两个子树中的最小边的路径上,这些边排除掉,剩下的边里面最大的就是答案
#include <iostream> #include <cstring> #include <cstdio> #include <cstdlib> #include <vector> #include <queue> #include <map> #include <algorithm> using namespace std; #define N 10500 #define M 200500 #define INF 100000000 int n,m,ans; struct Edge { int v,w; Edge() {v=0;w=0;} Edge(int _v,int _w) {v=_v;w=_w;} }edge[M]; int head[N],adj[M],e; int dfn[N],low[N],cnt; int sta[N],sum,top,scc[N]; vector<Edge>vec[N]; void dfs(int u,int preedge) // preedge 解决重边 { dfn[u]=low[u]=++cnt; sta[top++]=u; for(int i=head[u];i!=-1;i=adj[i]) { int v=edge[i].v; if(dfn[v]==0) { dfs(v,i); low[u]=min(low[u],low[v]); } else if((i^1)==preedge) continue; else low[u]=min(low[u],dfn[v]); } if(low[u]==dfn[u]) { int i; ++sum; do { i=sta[--top]; scc[i]=sum; }while(i!=u); } } void insert(int u,int v,int w) { edge[e].v=v;edge[e].w=w; adj[e]=head[u];head[u]=e++; edge[e].v=u;edge[e].w=w; adj[e]=head[v];head[v]=e++; } void init() { memset(head,-1,sizeof(head)); e=0;cnt=sum=top=0; for(int i=0;i<=n+5;++i) dfn[i]=low[i]=scc[i]=0; } //缩点后形成一颗树,敌人的策略是在树上加条边产生个环,这个环我放无法破坏其连通性 //为了让我方付出更大的代价敌人一定把权值小的边放在环上, //最坏的情况是第一小和第二小的边都在环上 //找出第一小的边,以两端点为起点dfs,每次在一个节点,都找出含有最小权边的子树,开下去 //取第二小的边更新ans int dfs2(int u,int fa) { int m1=INF,m2=INF,v,temp,w; for(int i=0;i<vec[u].size();++i) { v=vec[u][i].v; if(v==fa) continue; w=vec[u][i].w; if(w<m2) m2=w; temp=dfs2(v,u); if(temp<m2) m2=temp; if(m2<m1) swap(m1,m2); } if(m2<ans) ans=m2; return m1; } int main () { //freopen("input.txt","r",stdin); //freopen("output.txt","w",stdout); while(scanf("%d%d",&n,&m)!=EOF) { int u,v,w; init(); for(int i=1;i<=m;++i) { scanf("%d%d%d",&u,&v,&w); insert(u,v,w); } for(int i=1;i<=n;++i) if(!dfn[i]) dfs(i,-1); for(int i=0;i<=sum;++i) vec[i].clear(); int min_edge,st=-1,ed=-1; min_edge=INF; for(u=1;u<=n;++u) for(int i=head[u];i!=-1;i=adj[i]) if(scc[u]!=scc[edge[i].v]) { vec[scc[u]].push_back(Edge(scc[edge[i].v],edge[i].w)); if(min_edge>edge[i].w) min_edge=edge[i].w,st=scc[u],ed=scc[edge[i].v]; } ans=INF; if(st==-1||ed==-1) { printf("-1\n"); continue; } dfs2(st,ed); dfs2(ed,st); if(ans>=INF) printf("-1\n"); else printf("%d\n",ans); } //system("pause"); return 0; }