ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

HDU 4005 The war(边双连通)

2019-12-16 13:01:44  阅读:219  来源: 互联网

标签:HDU 边双 bel min int chk 4005 dfn head


题意

​ 给定一张 \(n\) 个点 \(m\) 条边的无向连通图,加入一条边,使得图中权值最小的桥权值最大,如果能使图中没有桥则输出 \(-1\)。

思路

​ 先对原图边双缩点,然后变成了一棵树。在树上加一条边等价于使一条路径上的边都不是桥,那么原题转化为在树上删一条路径,使得最小的边最大。固定一条最小的边之后模拟即可。

代码

#include<bits/stdc++.h>
#define FOR(i, x, y) for(int i = (x), i##END = (y); i <= i##END; ++i)
#define DOR(i, x, y) for(int i = (x), i##END = (y); i >= i##END; --i)
template<typename T, typename _T> inline bool chk_min(T &x, const _T &y) {return y < x ? x = y, 1 : 0;}
template<typename T, typename _T> inline bool chk_max(T &x, const _T &y) {return x < y ? x = y, 1 : 0;}
typedef long long ll;
const int N = 10005;
const int M = 100005;

template<const int N, const int M, typename T> struct Linked_List
{
    int head[N], nxt[M], tot; T to[M];
    Linked_List() {clear();}
    T &operator [](const int x) {return to[x];}
    void clear() {memset(head, -1, sizeof(head)), tot = 0;}
    void add(int u, T v) {to[tot] = v, nxt[tot] = head[u], head[u] = tot++;}
    #define EOR(i, G, u) for(int i = G.head[u]; ~i; i = G.nxt[i])
};

struct edge {int to, cost;};
Linked_List<N, M << 1, edge> G;
Linked_List<N, N << 1, edge> T;

int dfn[N], low[N], stk[N], bel[N], dfn_idx, tp, bcc;
int miner[N], son[N];
int n, m;

void tarjan(int u, int fa_e)
{
    dfn[u] = low[u] = ++dfn_idx, stk[++tp] = u;
    EOR(i, G, u)
    {
        if(i == (fa_e ^ 1)) continue;
        int v = G[i].to;
        if(!dfn[v]) tarjan(v, i), chk_min(low[u], low[v]);
        else if(dfn[v] < dfn[u]) chk_min(low[u], dfn[v]);
    }
    if(dfn[u] == low[u])
    {
        bcc++;
        do bel[stk[tp]] = bcc; while(stk[tp--] != u);
    }
}

void dfs(int u, int f)
{
    miner[u] = 2e9, son[u] = 0;
    EOR(i, T, u)
    {
        int v = T[i].to, w = T[i].cost;
        if(v == f) continue;
        dfs(v, u);
        if(chk_min(miner[u], miner[v])) son[u] = v;
        if(chk_min(miner[u], w)) son[u] = v;
    }
}

int redfs(int u, int f)
{
    if(!son[u]) return 2e9;
    int res = redfs(son[u], u);
    EOR(i, T, u)
    {
        int v = T[i].to, w = T[i].cost;
        if(v == f || v == son[u]) continue;
        chk_min(res, miner[v]);
        chk_min(res, w);
    }
    return res;
}

int main()
{
    while(~scanf("%d%d", &n, &m))
    {
        G.tot = T.tot = 0;
        FOR(i, 1, n) G.head[i] = T.head[i] = -1;
        FOR(i, 1, n) dfn[i] = 0;
        bcc = dfn_idx = 0;

        FOR(i, 1, m)
        {
            int u, v, w;
            scanf("%d%d%d", &u, &v, &w);
            G.add(u, (edge){v, w}), G.add(v, (edge){u, w});
        }

        tarjan(1, -1);

        int s, t, mi = 2e9;
        FOR(u, 1, n) EOR(i, G, u)
        {
            int v = G[i].to, w = G[i].cost;
            if(bel[u] < bel[v])
            {
                if(chk_min(mi, w)) s = bel[u], t = bel[v];
                T.add(bel[u], (edge){bel[v], w}), T.add(bel[v], (edge){bel[u], w});
            }
        }

        dfs(s, t), dfs(t, s);
        int res = std::min(redfs(s, t), redfs(t, s));
        printf("%d\n", (res > 1e9 ? -1 : res));
    }
    return 0;
}

标签:HDU,边双,bel,min,int,chk,4005,dfn,head
来源: https://www.cnblogs.com/Paulliant/p/12048559.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有