hdu3394Railway(双连通)
题意: 高速路即无向图,最后修建的高速路需要两两连通且路径不唯一(形成环,点双连通),第二问就是把不构成环的高速路去掉,即桥
第一问是求那些两两之间路径超过两条的边,即连通分量中有两个以上的环,如果连通分量中点的个数<边的个数,就能说明满足了,然后
我想吐槽一下hdu那个测评,我明明是数组开小了,非要说我超时,我还在哪找半天错....
#include<bits/stdc++.h> using namespace std; const int maxn = 100100; //之前少开了个0... typedef long long ll; int n, m; int s1, s2; struct edge { int f,t, nxt; }e[maxn<<1]; int hd[maxn], tot; void add(int f, int t) { e[++tot] = { f,t,hd[f] }; hd[f] = tot; } int low[maxn], dfn[maxn],cnt; stack<edge>S; set<int>col; void dfs(int u, int f) { dfn[u] = low[u] = ++cnt; for (int i = hd[u]; i; i = e[i].nxt) { int v = e[i].t; if (v == f)continue; if (!dfn[v]) { S.push(e[i]); dfs(v, u); low[u] = min(low[u], low[v]);//更新low值 if (low[v] >= dfn[u]) {//割点 //把连通分量里的所有边找出来,如果边的数目大于点的数目,即由至少两个环形成,则满足条件 col.clear(); edge tmp; int edgecnt = 0; do { edgecnt++; tmp = S.top(); S.pop(); col.insert(tmp.f); col.insert(tmp.t); } while (tmp.f != u || tmp.t != v); if (edgecnt > col.size()) { s1 += edgecnt; } } if (low[v] > dfn[u]) {//桥,桥不属于环,是可以不必修建的 s2++; } } else if (dfn[v] < dfn[u]) {//回退边(指向dfs路径上的某个点) S.push(e[i]); low[u] = min(low[u], dfn[v]); } } } int main() { //freopen("test.txt", "r", stdin); while (~scanf("%d%d", &n, &m)) { if (n == 0&&m==0)break; cnt = s1 = s2 = tot = 0; memset(hd, 0, sizeof(hd)); memset(dfn, 0, sizeof(dfn)); while (m--) { int a, b; scanf("%d%d", &a, &b); add(a, b); add(b, a); } for (int i = 0; i < n; i++) { if (!dfn[i]) { dfs(i, -1); } } printf("%d %d\n", s2, s1); } return 0; }