hdu4005The war tarjan缩点

//给一个连通无向图,加上一条边需要删除一条边,使得这个图不连通
//删除边需要花费钱,问最少需要准备多少钱使得不论加什么边最终都可以最终删除一条边使得原图不连通
//所需要删的边一定是桥,所以先进行缩点使得其变为一棵树
//在一棵树上加一条边后使得其有一个环,删除这个环的边后其依然连通
//最坏的情况权值最小的边在这个环中,而且其必然是连接两个叶子节点,这样使得环覆盖的边尽量多
//所以可以以权值最小的边将这棵树分为两棵,可以分别从这一最小边的两个端点为根节点出发
//分别搜索这两棵树的经过其最小的边(不是上面的最小边)的路径,除了这个路径上的边以及这个最小边的端点为根的子树中所有的边
//剩下的边的最小值即为答案
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std ;
const int maxn = 200010 ;
const int inf = 0x7fffffff ;
int vis[maxn] ;int dfn[maxn] , low[maxn] ;
int isstack[maxn] , stack[maxn] ,belong[maxn];
int head[maxn] ;   int n , m ;
int nedge , num , step , top ;int ans ;
struct Edge
{
    int u;int v ;int w ;
    int next ;
}edge[maxn] ;
vector<Edge> vec[maxn] ;
void addedge(int u , int v , int w)
{
    edge[nedge].v = v ;
    edge[nedge].w = w ;
    edge[nedge].next = head[u] ;
    head[u] = nedge++ ;
    edge[nedge].v = u ;
    edge[nedge].w = w ;
    edge[nedge].next = head[v] ;
    head[v]  =  nedge++ ;
}
void init()
{
    memset(dfn , 0 , sizeof(dfn)) ;
    memset(head , -1  ,sizeof(head)) ;
    memset(vis ,0 , sizeof(vis)) ;
    memset(isstack , 0 , sizeof(isstack)) ;
    for(int i = 0;i <= n;i++)
    vec[i].clear() ;
    nedge = num = step = top = 0 ;
}
void tarjan(int u)
{
    stack[++top] = u ;
    isstack[u] = 1 ;
    low[u] = dfn[u] = ++step ;
    for(int i = head[u] ; i != -1 ;i = edge[i].next)
    {
        if(vis[i])continue ;
        vis[i] = vis[i^1] = 1 ;
        int v = edge[i].v ;
        if(!dfn[v])
        {
            tarjan(v) ;
            low[u] = min(low[u] , low[v]) ;
        }
        else  if(isstack[v])
        low[u] = min(low[u] , dfn[v]) ;
    }
    if(low[u] == dfn[u])
    {
        num++ ;
        int v = 0;
        while(v!=u)
        {
            v = stack[top--] ;
            isstack[v] = 0 ;
            belong[v] = num ;
        }
    }
}
Edge build_tree()
{
    Edge tmp ;tmp.w = inf ;
    for(int i = 1;i <= n;i++)
      for(int j = head[i] ; j != -1 ;j = edge[j].next)
      {
          int u = belong[i] ;
          int v = belong[edge[j].v] ;
          if(u == v)continue ;
          Edge newedge = {u , v , edge[j].w,0} ;
          if(edge[j].w < tmp.w)
          {
              tmp.w = edge[j].w ;
              tmp.u = u ;
              tmp.v = v ;
          }
          vec[u].push_back(newedge);
      }
    return tmp ;
}
int dfs(int u , int pre)
{
    int mi_f = inf, mi_s = inf;
    for(int i = 0;i < vec[u].size() ;i++)
    {
        int v = vec[u][i].v ;
        if(v == pre)continue ;
        int sum = min(vec[u][i].w , dfs(v , u)) ;
        if(sum <= mi_f)
        {
            mi_s = mi_f ;
            mi_f = sum ;
        }
        else mi_s = min(mi_s , sum) ;
    }
    ans = min(ans , mi_s) ;
    return mi_f ;
}
void debug()
{
    for(int i = 1;i <= num;i++)
     for(int j = 0;j < vec[i].size();j++)
        printf("%d %d %d\n" , i , vec[i][j].v , vec[i][j].w) ;
}
int main()
{
    //freopen("in.txt" , "r" , stdin) ;
    while(~scanf("%d%d" , &n , &m))
    {
        int u , v , w ;
        init() ;
        while(m--)
        {
            scanf("%d%d%d" , &u ,&v ,&w) ;
            addedge(u , v , w) ;
        }
        tarjan(1) ;
        Edge tmp = build_tree() ;
        ans = inf ;
        if(num == 1)
        {
            puts("-1");
            continue ;
        }
        dfs(tmp.u , tmp.v) ;
        dfs(tmp.v , tmp.u) ;
        if(ans == inf)puts("-1") ;
        else
        cout<<ans<<endl;
    }
}





























你可能感兴趣的:(Tarjan)