Caocao's Bridges

题目:Caocao’s Bridges
总结:用tarjan模板,但是需要注意有几个坑。如果不是连通图,直接输出0,如果没有桥输入-1,如果答案为0,输出1。
特别需要注意有重边,所以这个地方有个小技巧。看算法竞赛进阶指南P366

#include 
using namespace std;
typedef pair<int,int>P;
const int N = 1e3+10;
const int mod = 1000000007;
const int inf = 0x3f3f3f3f;

struct str{
     
    int dot,dis;
    int next;
}e[4*N*N];
int dfn[N],low[N],head[N];
int n,cnt,m,ans,cntn;

void init(){
     
    memset(head,0,sizeof head);
    memset(dfn,0,sizeof dfn);
    memset(low,0,sizeof low);
    cntn = 1;//这里需要从1开始,一定
    cnt = 0;
    ans = inf;
}
void add(int x,int y,int z){
     
    e[++cntn].dot = y;//cntn会从2开始
    e[cntn].dis = z;
    e[cntn].next = head[x];
    head[x] = cntn;
}
//就算对于有重边,它们的每条边都存放不同的起点和不同的终点
//所以每对i和i^1都是不同的
void tarjan(int u,int f){
     
    dfn[u] = low[u] = ++cnt;
    for(int i = head[u];i;i = e[i].next){
     
        int v = e[i].dot;
        if(!dfn[v]){
     
            tarjan(v,i);//防止有重边的情况,这个时候的i相当于递归之后的另一个起点
            low[u] = min(low[u],low[v]);
            if(dfn[u] < low[v]){
     
                ans = min(ans,e[i].dis);
            }
        }else if(i != (f^1)){
     //防止有重边的情况
            low[u] = min(low[u],dfn[v]);
        }
    }
}
void solve(){
     
    int k = 0;
    for(int i = 1;i <= n;i++){
     
        if(!dfn[i]){
     
            k++;
            tarjan(i,0);
        }
    }
    if(k > 1){
     
        printf("0\n");
        return ;
    }
    if(ans == inf){
     
        printf("-1\n");
    }else if(ans == 0){
     
        printf("1\n");
    }else printf("%d\n",ans);
}
int main(){
     
    while(scanf("%d%d",&n,&m)){
     
        if(n == 0 && m == 0) break;
        init();
        while(m--){
     
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            add(x,y,z);
            add(y,x,z);
        }
        solve();
    }
    return 0;
}

你可能感兴趣的:(连通图,HDU)