hdu 4005

http://acm.hdu.edu.cn/showproblem.php?pid=4005

思路:缩点之后形成一棵树,连任意两个点都能之后形成一个环,那么破坏这个环上的任意一个边都不会破坏图的连通性,我们只有破坏不在环上的边才能使图不连通。由于边是任意加的,我们当然要使最小的边尽量都在环里面。好了,这样的话我们可以先找一条最小边,因为如果最小边不在环里的话,那么破坏一个最小边就可以了。找到最小边了之后,以最小边的两个端点分别向两侧遍历一条路径,使得路径上的边的值都尽量小,也就是说使不在路径上的边的值的最小值尽量大,怎么做到呢?稍微想一下,在遍历的时候,对于每个点,他与各个儿子边的次小值(儿子边实际包含儿子子树上最小的边)的最小值就是答案,这样的话遍历两遍就好了。

ps:发现tarjan的写法有点不一样,如果按常规写,就wa。求解中~~~

View Code
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<stack>
#include<algorithm>
#include<utility>
using namespace std;
const int maxn = 10005;
struct nd
{
        int u,v,w,next;
}edge[maxn*20];
int dfn[maxn],low[maxn],vis[maxn],head[maxn],belong[maxn];
int ecnt,cnt,idx,n,m,ans;
int e[maxn*20][3],et;
stack<int>st;

void add(int s,int t,int w)
{
        edge[ecnt].u = s;
        edge[ecnt].v = t;
        edge[ecnt].w = w;
        edge[ecnt].next = head[s];
        head[s] = ecnt++;
}
void tarjan(int pre,int u)
{
        int i,v;
        dfn[u] = low[u] = ++idx;
        st.push(u);
        for(i = head[u]; i != -1; i = edge[i].next)
        {
                v = edge[i].v;
                if(v==pre)continue;
                if(!dfn[v])
                {
                        tarjan(u,v);
                        low[u] = min(low[u],low[v]);
                        if(dfn[u]<low[v])
                        {
                                e[++et][0] = u;
                                e[et][1] = v;
                                e[et][2] = edge[i].w;
                        }
                }else  low[u] = min(low[u],dfn[v]);
        }
        if(dfn[u]==low[u])
        {
                cnt++;
                do{
                        v = st.top();
                        st.pop();
                        belong[v] = cnt;
                }while(v!=u);
        }
}

int dfs(int pre,int u)
{
        int i,v;
        int m1=1e9,m2=1e9,r=1e9;
        for(i = head[u]; i != -1; i = edge[i].next)
        {
                v = edge[i].v;
                if(v==pre)continue;
                int w = dfs(u,v);
                if(w<m2) m2 = w;
                if(edge[i].w < m2) m2 = edge[i].w;
                if(m1>m2) swap(m1,m2);
                if(m1<r)r = m1;
        }
        if(ans>m2) ans = m2;
        return r;
}

int main()
{
        int i,j,k,s,t,w;
        int ss,tt,ww;
        while(scanf("%d %d",&n,&m)==2)
        {
                memset(dfn,0,sizeof(dfn));
                memset(low,0,sizeof(low));
                memset(vis,0,sizeof(vis));
                memset(head,-1,sizeof(head));
                ecnt = 0;
                for(i = 0; i < m; ++ i)
                {
                        scanf("%d %d %d",&s,&t,&w);
                        add(s,t,w);
                        add(t,s,w);
                }
                while(!st.empty()) st.pop();
                cnt = idx = 0; et = 0;
                tarjan(0,1);
                k = ecnt;
                ecnt = 0;
                memset(head,-1,sizeof(head));
                ww = 1e9;
                ss = tt = -1;
                for(i = 1; i <= et; ++ i)
                {
                        s = e[i][0];
                        t = e[i][1];
                        w = e[i][2];
                        add(belong[s],belong[t],w);
                        add(belong[t],belong[s],w);
                        if(ww>w){ ss = belong[s]; tt = belong[t]; ww = w;}
                }
                ans = 1e9;
                if(ss!=-1){
                        dfs(ss,tt);
                        dfs(tt,ss);
                }
                if(ans<1e9) printf("%d\n",ans);
                else puts("-1");
        }return 0;
}

 

 

posted on 2012-06-20 21:22  aigoruan  阅读(368)  评论(0)    收藏  举报

导航