1. 程式人生 > >HDU ~ 4738 ~ Caocao's Bridges (橋)

HDU ~ 4738 ~ Caocao's Bridges (橋)

題意

輸入N,M,然後輸入M條邊(u,v,w)表示u-v有一條邊權為w的無向邊,求w最小的橋,輸出w。如果不存在橋輸出-1,圖不連通輸出0。

思路

模板題?就是有兩個坑點,①有重邊②圖不連通輸出0

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 5;
const int INF = 0x3f3f3f3f;

struct Edge
{
    int from, to, num;
    Edge(int from, int to, int num): from(from), to(to), num(
num) {} }; struct CUT { int n, m; vector<Edge> edges; vector<int> G[MAXN]; int DFN[MAXN], LOW[MAXN], dfs_clock; //時間戳,返祖邊到達的最小的祖先,計時 int iscut[MAXN]; //割點 vector<Edge> cut; //橋 void init(int n) { this->
n = n; edges.clear(); for (int i = 0; i <= n; i++) G[i].clear(); } void AddEdge(int from, int to, int num) { edges.push_back(Edge(from, to, num)); edges.push_back(Edge(to, from, num)); m = edges.size(); G[from].push_back(m-2); G[to]
.push_back(m-1); } int dfs(int u, int fa) { int lowu = DFN[u] = ++dfs_clock; int child = 0; bool flag = false; for (int i = 0; i < G[u].size(); i++) { Edge& e = edges[G[u][i]]; int v = e.to; //重邊不算橋,只跳過第一條fa~u的邊;如果重邊也算橋就把所有的v==fa的邊跳過 if (v == fa && !flag) { flag = true; continue; } if (!DFN[v])//樹邊 { child++; int lowv = dfs(v, u); lowu = min(lowu, lowv); if (lowv >= DFN[u])//割點 iscut[u] = true; if (lowv > DFN[u])//橋 cut.push_back(e); } else //返祖邊 lowu = min(lowu, DFN[v]); } if (fa < 0 && child == 1) iscut[u] = false; LOW[u] = lowu; return lowu; } int find_cut() { int cnt = 0; dfs_clock = 0; memset(DFN, 0, sizeof(DFN)), memset(LOW, 0, sizeof(LOW)); cut.clear(), memset(iscut, 0, sizeof(iscut)); for (int i = 0; i < n; i++) if (!DFN[i]) cnt++, dfs(i, -1); return cnt; } }gao; int n, m; int main() { while (~scanf("%d%d", &n, &m) && (n+m)) { gao.init(n); while (m--) { int u, v, w; scanf("%d%d%d", &u, &v, &w); u--, v--; gao.AddEdge(u, v, w); } if (gao.find_cut() > 1) { printf("0\n"); continue; } int ans = INF; for (auto& i: gao.cut) ans = min(ans, i.num); if (ans == 0) ans = 1; if (ans == INF) ans = -1; printf("%d\n", ans); } return 0; } /* 3 3 1 2 7 2 3 4 3 1 4 3 2 1 2 7 2 3 4 0 0 */