HDU 4738 无向图求桥

使用tarjan算法求桥,模板题,但是。。。

1.有重边

2.不一定连通

3.没有人守桥至少要派一个人去

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

这种题挺好的,可以锻炼人的耐性和心理承受能力。。。

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <vector>
using namespace std;
const int N = 1000 + 5;
const int INF = 0x3f3f3f3f;
int n,m;
int dfs_clock, pre[N], low[N];

struct Edge
{
    int u,v,w;
    int iscut;
    Edge() {}
    Edge(int a, int b, int c, int d):u(a), v(b), w(c), iscut(d) {}
};
vector<Edge> edges;
vector<int> G[N];
void addedge(int u, int v, int w)
{
    edges.push_back(Edge(u, v, w, 0));
    edges.push_back(Edge(v, u, w, 0));
    int m = edges.size();
    G[u].push_back(m-2);
    G[v].push_back(m-1);
}
void init()
{
    edges.clear();
    for(int i = 0; i <= 1000; i++)
        G[i].clear();
    memset(pre, 0, sizeof(pre));
    memset(low, 0, sizeof(low));
    dfs_clock = 0;
}
int tarjan(int u, int fa)
{
    int lowu = pre[u] = ++dfs_clock;
    int flag = 1;
    for(int i = 0; i < G[u].size(); i++)
    {
        Edge &e = edges[G[u][i]];
        int v = e.v,lowv;
        if(flag && v == fa)
        {
            flag = 0;
            continue;
        }
        if(!pre[v])
        {
            lowv = tarjan(v, u);
            lowu = min(lowu, lowv);
            if(lowv > pre[u])
            {
                e.iscut = 1;
                edges[G[u][i]^1].iscut = 1;
            }
        }
        else
        {
            lowu = min(lowu, pre[v]);
        }
    }
    low[u] = lowu;
    return lowu;
}

int main()
{
    while(scanf("%d%d", &n, &m),n||m)
    {
        init();
        for(int i = 0; i < m; i++)
        {
            int u,v,w;
            scanf("%d%d%d", &u,&v,&w);
            addedge(u,v,w);
        }
        tarjan(edges[0].u, -1);
        int flag = 0;
        for(int i = 1; i <= n; i++)
            if(pre[i] == 0)
            {
                flag = 1;
                break;
            }
        if(flag)
        {
            printf("0\n");
            continue;
        }
        int ans = INF;
        for(int i = 0; i < edges.size(); i++)
        {
            if(edges[i].iscut)
            {
                ans = min(ans, edges[i].w);
            }
        }
        if(ans == INF)
            printf("-1\n");
        else
            printf("%d\n", ans == 0 ? 1 : ans);
    }
}
时间: 2024-10-10 10:14:37

HDU 4738 无向图求桥的相关文章

I - Caocao&#39;s Bridges - hdu 4738(求桥)

题意:曹操的船之间有一些桥连接,现在周瑜想把这些连接的船分成两部分,不过他只能炸毁一座桥,并且每座桥上有士兵看守,问,他最少需要排多少士兵去炸桥如果不能做到,输出‘-1’ 注意:此题有好几个坑,第一个输入桥守卫是0的话也得排一个士兵 如果一开始桥就是不连通的就不用派士兵了,直接输出 0 ************************************************************** #include<stdio.h>#include<string.h>#

HDU 4738 无向图的桥

Caocao's Bridges Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1876    Accepted Submission(s): 679 Problem Description Caocao was defeated by Zhuge Liang and Zhou Yu in the battle of Chibi. Bu

HDU 3849 无向图求桥

By Recognizing These Guys, We Find Social Networks Useful Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 125536/65536 K (Java/Others)Total Submission(s): 2563    Accepted Submission(s): 671 Problem Description Social Network is popular these

hdu 2242 无向图/求用桥一分为二后使俩个bcc点权值和之差最小并输出 /缩点+2次新图dfs

题意如标题所述, 先无向图缩点,统计出每个bcc权,建新图,然后一遍dfs生成树,标记出每个点(新图)以及其子孙的权值之和.这样之后就可以dfs2来枚举边(原图的桥),更新最小即可. 调试了半天!原来是建老图时候链式前向星和新图的vector<vector< int>>俩种存图搞乱了!!!不可原谅!哎!愚蠢!愚不可及!提交后1A. 后来百度之后,发现说是用树形dp,看了代码解法,竟然和我的是一样的算法..原来这种算法可以叫树形dp...的确有点dp味道..不过感觉不太浓.. 以后多

hdu 4738 无向图缩点断桥 // 细节坑题

Caocao's Bridges 题意:给个无向图,求出边权最小的桥. 一看,直接缩点,若无桥,输出-1,有桥,遍历下边,更新最小..分分钟搞定,以为IA的..一交wa... 坑点:1:若原图不连通,则无须派人去!输出0!: 2:若桥的权是0,则还有派一个人把炸弹拿去,输出1! 3:有重边.(按多条边算). 哎!记住这个教训!以后做题 1:考虑边界或者特殊数据!(边权为0!n==1等) 2:考虑原图连通性!(这次考虑了原图就强连通..没有考虑根本不连通!) 3:重边.这题的重边是按重边算(不是一

UVA 796 Critical Links(无向图求桥)

题目来源: UVa Online Judgehttps://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=737 求一个连通图中必不可少的路径: #include<stdio.h> #include<algorithm> #include<vector> #include<string.h> #define

POJ 3694 Network(无向图求桥+重边处理+LCA)

题目大意: 给你一个无向图,然后再给你一个Q代表有Q次询问,每一次加一条边之后还有几座桥.在这里要对重边进行处理. 每次加入一条边之后,在这条搜索树上两个点的公共祖先都上所有点的桥都没了. 这里重边的处理上要说一下, 我以前第一写的时候根本没考虑这个问题,但是居然过了...过了...  很扯淡,但是重边的问题确实是存在. 这里我们 使用一个 bridge 数组来保存桥, 因为有重边的存在  只有 bridge 数量为 1 的时候这个路径才算是桥,否则则不是桥 bridge[i] 是指  i 和

poj 3694 无向图求桥+lca

题意抽象为: 给一个无向图和一些询问 对于每一次询问: 每次询问都会在图上增加一条边 对于每一次询问输出此时图上桥的个数. 桥的定义:删除该边后原图变为多个连通块. 数据规模:点数N(1 ≤ N ≤ 100,000) ,边数M(N - 1 ≤ M ≤ 200,000),询问数Q ( 1 ≤ Q ≤ 1,000) 先跑一遍tarjan,对边双连通分枝缩一下点. 再维护lca即可. AC代码: #include<cstdio> #include<cstring> #include<

无向图求桥,允许重复边

#include <iostream> #include <map> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <vector> #include <queue> #include <set> #define LL long long #define INF 0x3f3f3f