hdu4738——tarjan割边

hdu4738
题意
n个岛m座桥的无向图,每座桥上有若干个士兵,派出最少的士兵只炸毁一座桥,使得n个岛不连通(派出的士兵不能少于驻守的士兵,特别的改桥的驻守人数为0的时候要派一个士兵)。
思路
用tarjan算法,满足dfn[u] < low[v]的(u,v)就是割边,直接处理出来取最小值,这里还有一个问题就是有重边,所以要判断一下。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e3 +7;
const int maxm = 1000000 + 7;
typedef long long ll;
int n, m, low[maxn], dfn[maxn], vis[maxn], tot;//scc连通分量数
int head[maxn], to[maxm], nex[maxm], edge[maxm], cnt;
stack<int> st;//辅助栈
int e[maxn][maxn];
void add(int x, int y, int z) {
    to[cnt] = y;
    edge[cnt] = z;
    nex[cnt] = head[x];
    head[x] = cnt++;
}
vector<int> g;
void tarjan(int u, int fx)
{
    dfn[u] = low[u] = ++tot;
    st.push(u);
    vis[u] = 1;
    for (int i = head[u]; ~i; i = nex[i]) {
        int v = to[i];
        if(!dfn[v]) {//如果没访问过
            tarjan(v, u);
            low[u] = min(low[u], low[v]);//能连通到的最小根
            if(dfn[u] < low[v] && e[u][v] == 1) {//把重边问题排除
                g.push_back(edge[i]);
            }
        }
        else if(v != fx)//不走反路
            low[u] = min(low[u], dfn[v]);
    }
}
int main()
{
    while (scanf("%d%d", &n, &m) && n)
    {
        g.clear();
        memset(low, 0, sizeof(low));
        memset(dfn, 0, sizeof(dfn));
        memset(vis, 0, sizeof(vis));
        memset(head, -1, sizeof(head));
        memset(e, 0, sizeof(e));
        tot = cnt = 0;
        while (!st.empty()) st.pop();
        for (int i = 1; i <= m; i++) {
            int a, b, c;
            scanf("%d%d%d", &a, &b, &c);
            add(a, b, c);
            add(b, a, c);
            e[a][b]++;
            e[b][a]++;
        }
        tarjan(1, 1);
        bool f = 1;
        for (int i = 1; i <= n; i++) {
            if(dfn[i] == 0) {
                f = 0;
                break;
            }
        }
        if(!f) {
            printf("0\n");
            continue;
        }
        int ans = 0x3f3f3f3f;
        for (int i = 0; i < g.size(); i++)
            ans = min(ans, g[i]);
        if(ans == 0x3f3f3f3f) {
            printf("-1\n");
            continue;
        }
        if(ans == 0) ans = 1;
        printf("%d\n", ans);
    }
}

发布了26 篇原创文章 · 获赞 2 · 访问量 401

猜你喜欢

转载自blog.csdn.net/D_Bamboo_/article/details/103907136