Hdu 4738【tanjan求无向图的桥】

题目:

  曹操在长江上建立了一些点,点之间有一些边连着。如果这些点构成的无向图变成了连通图,那么曹操就无敌了。刘备为了防止曹操变得无敌,就打算去摧毁连接曹操的点的桥。但是诸葛亮把所有炸弹都带走了,只留下一枚给刘备。所以刘备只能炸一条桥。

  题目给出n,m。表示有n个点,m条桥。

  接下来的m行每行给出a,b,c,表示a点和b点之间有一条桥,而且曹操派了c个人去守卫这条桥。

  现在问刘备最少派多少人去炸桥。

  如果无法使曹操的点成为多个连通图,则输出-1.

 

思路:

  就是用tarjan算法算出桥的数量,再比较哪一个的值最小。

Tips:

  注意三点:

  ①. 有重边,所以tarjan算法要处理重边。有两种处理方法,一种是先把所有的边存下,发现两点有重边的时候就只给这两个点连一条权值为无穷大的边。或者是在tarjan算法里处理重边,即使之求u或u的子树能够追溯到的最早的栈中节点的次序号时可访问父节点的次序号。

  ②. 如果无向图图本身已经有两个连通图了,就无需派人去炸桥,这时候输出0。

  ③. 如果求出来的最小权值桥的守卫人数为0时,也需要派出一个人去炸桥。

Code:

// tarjan算法求无向图的桥、边双连通分量并缩点
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include <bits/stdc++.h>
#define cls(s,h) memset(s,h,sizeof s)
using namespace std;
const int N = 1010;
int n, m ;
struct edge
{
    int to;
    int pre;
    int id;
    int w;
};
edge E[N*N];
int head[N],tot;
//int soldier[N][N];//第一种方法所需的的邻接矩阵
int low[N],dfn[N],ts,top,st[N],ins[N];
int minn;

void init()
{
    cls(head,-1);
    tot=0;
    //CLR(soldier,INF);
    cls(low,0);
    cls(dfn,0);
    ts=top=0;
    cls(ins,0);
    minn=1e8;
}
inline void add(int s,int t,int w,int id)
{
    E[tot].to=t;
    E[tot].id=id;
    E[tot].w=w;
    E[tot].pre=head[s];
    head[s]=tot++;
}
void tarjan(int u,int id)
{
    low[u]=dfn[u]=++ts;
    ins[u]=1;
    st[top++]=u;
    int v;
    for (int i=head[u]; ~i; i=E[i].pre)
    {
        v=E[i].to;
        if(id==E[i].id)
            continue;
        if(!dfn[v])
        {
            tarjan(v,E[i].id);
            low[u]=min<int>(low[v],low[u]);
            if(low[v]>dfn[u])
            {
                int need=E[i].w;
                if(need<minn)
                    minn=need;
            }
        }
        else if(ins[v])
            low[u]=min<int>(low[u],dfn[v]);
    }
    if(low[u]==dfn[u])
    {
        do
        {
            v=st[--top];
            ins[v]=0;
        }
        while (u!=v);
    }
}

int main()
{
    while(scanf("%d%d",&n,&m)&&n+m)
    {
        init();

        //tot = 1;
        for (int i = 1; i <= m; i++)
        {
            int x, y,z;
            scanf("%d%d%d", &x, &y,&z);
            add(x, y,z,i), add(y,x,z,i);
        }
        int k = 0;
        minn = 1e8;
        for (int i = 1; i <= n; i++)
            if (!dfn[i]) tarjan(i, -1),k++;
        //for (int i = 2; i < tot; i += 2)
        //    if (bridge[i])
        //    printf("%d %d\n", ver[i ^ 1], ver[i]);

//    for (int i = 1; i <= n; i++)
        //    if (!c[i]) {
        //        ++dcc;
        //        dfs(i);
        //    }
        //printf("There are %d e-DCCs.\n", dcc);
        //for (int i = 1; i <= n; i++)
        //    printf("%d belongs to DCC %d.\n", i, c[i]);

        //for (int i = 2; i <= tot; i++) {
        //    int x = ver[i ^ 1], y = ver[i];
        //    if (c[x] == c[y]) continue;
        //    add_c(c[x], c[y]);
//    }
        //printf("缩点之后的森林,点数 %d,边数 %d\n", dcc, tc / 2);

        //for (int i = 2; i < tc; i += 2)
        //printf("%d %d %d\n", vc[i ^ 1], vc[i],edge[i]);
        //    minn = min(minn,edge[i]);
        if(k > 1)
            minn = 0;
        else if(minn == 0)
            minn = 1;
        else if(minn == 1e8)
            minn = -1;
        printf("%d\n",minn);

    }
    return 0;
}

原文地址:https://www.cnblogs.com/DWVictor/p/11332100.html

时间: 2024-10-10 10:30:26

Hdu 4738【tanjan求无向图的桥】的相关文章

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

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

hdu 4738 Caocao&#39;s Bridges(桥的最小权值+去重)

http://acm.hdu.edu.cn/showproblem.php?pid=4738 题目大意:曹操有一些岛屿被桥连接,每座都有士兵把守,周瑜想把这些岛屿分成两部分,但他只能炸毁一条桥,问最少需要派几个士兵去;如果不能完成输出-1 1:如果这些岛屿不连通,则不需要派人前去 2:如果桥的守卫是0的话也得派一人去炸毁 3:如果不能完成输出-1 4:输出最少需派的人数 #include<stdio.h> #include<string.h> #include<math.h&

【求无向图的桥,有重边】ZOJ - 2588 Burning Bridges

模板题——求割点与桥 题意,要使一个无向图不连通,输出必定要删掉的边的数量及其编号.求桥的裸题,可拿来练手. 套模板的时候注意本题两节点之间可能有多条边,而模板是不判重边的,所以直接套模板的话,会将重边也当做桥输出,因此要在判断桥的时候加一个判断,即当且仅当两点之间仅有一条边,且满足dfn[cur] < low[i],(cur, i)才是桥. 另外本题节点数为105,用邻接矩阵的话会内存超限,所以我用了了一个multiset存储边及其编号. 代码如下: 1 #include<cstdio>

Light OJ - 1026 - Critical Links(图论-Tarjan算法求无向图的桥数) - 带详细注释

 原题链接   无向连通图中,如果删除某边后,图变成不连通,则称该边为桥. 也可以先用Tajan()进行dfs算出所有点 的low和dfn值,并记录dfs过程中每个 点的父节点:然后再把所有点遍历一遍, 看其low和dfn,满足dfn[ fa ]<low[ i ](0<i<=n, i 的 father为fa) -- 则桥为fa-i. 找桥的时候,要注意看有没有重边:有重边,则不是桥. 另外,本题的题意及测试样例中没有重边,所以不用考虑重边. 带详细注释的题解: #include<s

HDU 4738 --Caocao&#39;s Bridges 【无向图边双联通 &amp;&amp; 求权值最小的桥 &amp;&amp; 模板】

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

HDU 4738 Caocao&#39;s Bridges tarjan求桥

Caocao's Bridges Problem Description Caocao was defeated by Zhuge Liang and Zhou Yu in the battle of Chibi. But he wouldn't give up. Caocao's army still was not good at water battles, so he came up with another idea. He built many islands in the Chan

HDU 4738——Caocao&#39;s Bridges——————【求割边/桥的最小权值】

Caocao's Bridges Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Practice HDU 4738 Description Caocao was defeated by Zhuge Liang and Zhou Yu in the battle of Chibi. But he wouldn't give up. Caocao's army st

HDU 4738 Caocao&#39;s Bridges ——(找桥,求联通块)

题意:给你一个无向图,给你一个炸弹去炸掉一条边,使得整个图不再联通,你需要派人去安置炸弹,且派去的人至少要比这条边上的人多.问至少要派去多少个,如果没法完成,就输出-1. 分析:如果这个图是已经是多个联通块了,那么一个人都不用去,如果不是,那么只要找出这个无向图上的桥并且哨兵数量最少的那座把它炸了就行(输出这条边上的哨兵数量即可).直接tarjan就可以写. 注意点:1.可能有重边,所以用手写邻接表的方式存图:2.如果一座桥上没有哨兵,那么你也得至少派去一个人去安置炸弹(因为炸弹不会自己飞过去啊

HDU 4738 Caocao&#39;s Bridges(求价值最小的桥)

Problem Description Caocao was defeated by Zhuge Liang and Zhou Yu in the battle of Chibi. But he wouldn't give up. Caocao's army still was not good at water battles, so he came up with another idea. He built many islands in the Changjiang river, and