hdu4005 缩点+无向图+重边

来源:互联网 发布:we假装情侣软件 编辑:程序博客网 时间:2024/06/05 00:09

奉上数据:

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 100000000int 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,每次在一个节点,都找出含有最小权边的子树,开下去//取第二小的边更新ansint 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;}