hdu Caocao's Bridges(无向图边双连通分量,找出权值最小的桥)

简介:

/*
    题意:给出一个无向图,去掉一条权值最小边,使这个无向图不再连同!
    
    tm太坑了...
    1,如果这个无向图开始就是一个非连通图,直接输出0
    2,重边(两个节点存在多条边, 权值不一样)
    3,如果找到了桥的最小权值为0,也就是桥上的士兵数为0,那么还是要最少派一个
    士兵过去炸掉桥! 
    
    思路:假设每两个节点最多只有一条边进行相连!
    进行tarjan算法,如果该算法调用了超过2次,说明这个原图就是不连通的!
    否则在tarjan算法中将桥存起来!然后我们遍历每一座桥,看一看我们找到的
    桥(连接的两个定点分别是u, v)是不是(u, v)只有一条路相连接,如果是的,
    那么就跟新最小值! 
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define M 1000005
#define INF 0x3f3f3f3f
#define N 1005
using namespace std;
struct EDGE{
   int u, v, w, nt; 
   EDGE(){}
   EDGE(int u, int v, int w, int nt){
       this->u=u;
       this->v=v;
       this->w=w;
       this->nt=nt;         
   }
};

EDGE edge[M];
EDGE brige[M];
int first[N];
int low[N], pre[N];
int dfs_clock;
int n, m, cnt, ret;


void tarjan(int u, int fa){
    low[u]=pre[u]=++dfs_clock;
    for(int e=first[u]; e!=-1; e=edge[e].nt){
         int v=edge[e].v;
        
         if(!pre[v]){
              tarjan(v, u);
              low[u]=min(low[u], low[v]);
              if(low[v]>pre[u])
                 brige[ret++]=edge[e];
         }         
         else if(v!=fa && pre[u]>pre[v])
              low[u]=min(low[u], pre[v]);
    }        
}

int main(){
    while(scanf("%d%d", &n, &m) && (n||m)){
        memset(first, -1, sizeof(first));
        cnt=0;
        while(m--){
            int u, v, w;
            scanf("%d%d%d", &u, &v, &w);
            edge[cnt]=EDGE(u, v, w, first[u]);
            first[u]=cnt++;
            edge[cnt]=EDGE(v, u, w, first[v]);
            first[v]=cnt++;
        }      
        dfs_clock=0;
        ret=0;
        memset(low, 0, sizeof(low));
        memset(pre, 0, sizeof(pre)); 
        int flag=0;
        for(int i=1; i<=n; ++i)
           if(!pre[i]){
              ++flag;
              if(flag==2) break;
              tarjan(i, -1);
           }
        
        int minNum=INF;
        if(flag==2) minNum=0;
        else{
           for(int i=0; i<ret; ++i)
             if(brige[i].w<minNum){//对假定的桥判断 
                int cc=0;
                for(int e=first[brige[i].u]; e!=-1; e=edge[e].nt)
                   if(edge[e].v==brige[i].v) ++cc;
                if(cc==1)  minNum=brige[i].w;//说明是真正的桥 
             }
           if(minNum==INF) minNum=-1;
           else if(minNum==0) minNum=1;//这一句不要忘记了! 
        }
        printf("%d\n", minNum);
    } 
    return 0;    
}

目录
相关文章
|
9月前
|
人工智能 BI
【每日一题Day232】LC2699修改图中的边权 |最短路径
【每日一题Day232】LC2699修改图中的边权 |最短路径
54 0
|
9月前
【每日一题Day287】LC24 两两交换链表中的节点 | 模拟 递归
【每日一题Day287】LC24 两两交换链表中的节点 | 模拟 递归
57 0
|
4月前
acwing 848 有向图的拓扑序列
acwing 848 有向图的拓扑序列
37 0
|
9月前
|
机器学习/深度学习
【每日一题Day181】LC1026节点与其祖先之间的最大差值 | 树形dp
【每日一题Day181】LC1026节点与其祖先之间的最大差值 | 树形dp
56 0
|
9月前
【每日一题Day223】LC1130叶值的最小代价生成树 | 贪心 区间dp
【每日一题Day223】LC1130叶值的最小代价生成树 | 贪心 区间dp
60 0
UVa10075 - Airlines(所有点对之间的最短距离)
UVa10075 - Airlines(所有点对之间的最短距离)
60 0
|
算法
Dijkstra算法:单元最短路径算法
Dijkstra算法:单元最短路径算法
209 0
|
存储
【每日一题Day106】LC1129 颜色交替的最短路径 | BFS
返回长度为 n 的数组 answer,其中 answer[X] 是从节点 0 到节点 X 的红色边和蓝色边交替出现的最短路径的长度。如果不存在这样的路径,那么 answer[x] = -1。
155 0
|
人工智能 Prometheus Cloud Native
牛客第五场 B Graph最小异或生成树
这道题涉及到最小异或生成树,要理解这个首先要明白 01字典树 关于01字典树呢,先来一道板子题hdu4825 ==》 不方便跳转的同学们可以看下面的题 Problem Description Zeus 和 Prometheus 做了一个游戏,Prometheus 给 Zeus 一个集合,集合中包含了N个正整数,随后 Prometheus 将向 Zeus 发起M次询问,每次询问中包含一个正整数 S ,之后 Zeus 需要在集合当中找出一个正整数 K ,使得 K 与 S 的异或结果最大。Prometheus 为了让 Zeus 看到人类的伟大,随即同意 Zeus 可以向人类求助。
137 0
牛客第五场 B Graph最小异或生成树
|
Go
[Nowcoder / POJ2728] 最优比率生成树 | 二分 + prim
有n个点,其中,每个点给出位置坐标( x , y ) 以及高度z ,两点之间的距离为两点之间的欧几里得距离 两点之间建立一条路的代价为两点之间的高度差,问将n 个点联通的情况下,求出最大的cost/dis
144 0

热门文章

最新文章