1. 程式人生 > >hdu 4005 邊雙聯通+LCA

hdu 4005 邊雙聯通+LCA

題意:

有一幅圖,現在要加一條邊,加邊之後要你刪除一條邊,使圖不連通,費用為邊的費用,要你求的是刪除的邊的最小值的最大值(每次都可以刪除一條邊,選最小的刪除,這些最小中的最大就為答案)

首先要進行縮點,把圖縮為一棵樹,因此,加入一條邊後圖就會存在一個環,環中的任何一條邊刪除後都不會導致圖不連通

之後找一條最小的邊,可以說這條邊肯定是在加邊之後的連通塊裡的,因為如果不在連通塊裡,那就直接可以把這條最小的邊刪掉,而達不到求出答案的目的

找到邊後,分別從邊的兩點開始遍歷,要遍歷出一條路徑來,並且邊上的權值要儘可能的小,因為這樣才能讓不在環中的邊儘可能的大,然後,答案就是每個節點的次小兒子的最小值,如果沒有次小兒子就不能算(就是說只有一個兒子,即節點不是三叉的),因為我完全可以把它和最小的邊放到一個連通塊中,那樣答案就應該更大了。

終上所述:先進行無向圖的縮點,再在樹上找最小的邊,最後分別從邊的兩點出發,遍歷樹,找節點的次小兒子節點中的最小值

舉個簡單的例子(括號內的數字代表邊上的權值)1和8間的權值為1,是最小的

                     1---8

                  /           \(3) 

        (2)/               \

             2                  3

    (4) /       \(5)    (6)/      \(7)

       /           \         /          \

     4              5     6              7

左子樹中2的子節點有次小值5,右子樹中3的子節點次小值為7,兩個次小值間的最小值是5,即答案

現在,比如所你要把3、4連起來。我可以去掉2、5之間的邊讓圖不連通,花費為5

把3、5連起來,我自然可以刪掉2、4,花費為4,

一個節點的次小值和最小值(比如說4、5兩點)不可能被同時連進一個連通塊(或環)中(因為必須把最小的那條邊加進環中),正是利用這個性質,不管把那兩個點連起來,我們都可以找到一個最小值或次小值來刪掉使圖不連通,注意:再重複一遍,同一個節點的最小值和次小值不會被加進同一個環,因此,這些次小值中的最小的那條邊的權值就是答案。(這時你如果把次小的邊加進環中,如2--5,自然可以刪掉一條更小的邊 如2--4 使圖不連通,相反,如果沒有把次小的邊加進去,那次小的就是答案)

#include<stdio.h>
#include<string.h>
#include<vector>
#include<algorithm>
#include<iostream>
using namespace std;
const int maxn = 10010;
int tot,n,m,ans;
const int inf = 999999999;
struct Edge
{
    int t,w;
    int next;
    int vis;
}edge[1000005];
int head[maxn],E;
void add(int s,int t,int w)
{
    edge[E].t=t;
    edge[E].w=w;
    edge[E].vis=0;
    edge[E].next=head[s];
    head[s]=E++;
}
int Btype,Time,N,M;
int dfn[maxn],low[maxn],belong[maxn];
int  st[maxn],Top;
int tt[100010][3],cnt;
inline int min(int a,int b){return a<b?a:b;}
void dfs(int s)
{
    int i,t;
    st[++Top]=s;
    dfn[s]=low[s]=++Time;
    for (i=head[s];i!=-1;i=edge[i].next)
    {    
        if(edge[i].vis)continue;    
        edge[i].vis=edge[i^1].vis=1;
        t=edge[i].t;
        if (!dfn[t])
        {
            dfs(t);
            low[s]=min(low[s],low[t]);
            if(dfn[s]<low[t])  
            {
                //printf("bug");
                tt[++cnt][0]=s,tt[cnt][1]=t,tt[cnt][2]=edge[i].w;
            }
        }
        else low[s]=min(low[s],dfn[t]);
    }
    if(dfn[s]==low[s])
    {
        Btype++;
        do{
            t=st[Top--];
            belong[t]=Btype;
        }while(t!=s);
    }
}
void SCC(int n)
{
    int i;
    Time=0;Btype=0;Top=0;
    memset(dfn,0,sizeof(int)*(n+1));
    for(i=1;i<=n;i++)if(!dfn[i])
        dfs(i);
}
int find(int s,int t)
{
    int i;
    int Min=inf,vice_Min=inf,rr=inf;
    for(i=head[s];i!=-1;i=edge[i].next)
    {
        int v=edge[i].t;
        if(v==t) continue;
        int w=find(v,s);//printf("w=%d\n",w);
        if(w<vice_Min) vice_Min=w; 
        if(edge[i].w<vice_Min) vice_Min=edge[i].w;
        if(Min>vice_Min) swap(vice_Min,Min);
        if(Min<rr) rr=Min;
    }
    if(ans>vice_Min) ans=vice_Min;
    return rr;
}
int a1,a2,flag;
int main()
{
    int i,a,b,w;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        memset(head,-1,sizeof(head));E=0;
        for(i=0;i<m;i++)
        {
            scanf("%d%d%d",&a,&b,&w);
            add(a,b,w);
            add(b,a,w);
        }
        cnt=0;     
        SCC(n);
        memset(head,-1,sizeof(head));E=0;
        int C=inf;
        for(i=1;i<=cnt;i++)
        {
        //    printf("s=%d t=%d\n",tt[i][0],tt[i][1]);
            add(belong[tt[i][0]],belong[tt[i][1]],tt[i][2]);
            add(belong[tt[i][1]],belong[tt[i][0]],tt[i][2]);
            if(tt[i][2]<C){C=tt[i][2]; a=belong[tt[i][0]],b=belong[tt[i][1]];}
        }
        ans=inf;
        find(a,b);
        find(b,a);
        if(ans==inf) printf("-1\n");
        else printf("%d\n",ans);
    }
    return 0;
}
/*
7 6
1 2 2
1 3 6
2 4 3
2 5 4
3 6 5
3 7 7
4
15 14
1 2 7
2 4 5
2 5 6
4 8 1
4 9 2
5 10 3
5 11 4
1 3 8
3 6 9
3 7 1
6 12 11
6 13 12
7 14 13
7 15 14
2
16 15
1 2 7
2 4 5
2 5 6
4 8 1
4 9 2
5 10 3
5 11 4
1 16 1
16 3 6
3 6 9
3 7 1
6 12 11
6 13 12
7 14 13
7 15 14
2
6 5
1 2 1
1 3 2
1 4 3
2 5 4
2 6 5
3
9 8
1 2 1
2 6 5
6 7 7
6 8 4
6 9 6
1 3 2
1 4 5
1 5 6
5
9 8
1 2 1
2 6 5
6 7 7
6 8 4
6 9 4
1 3 2
1 4 5
1 5 6
4*/