hdu3394--Railway(点的双连通分量)

一个公园中有 n 个景点,景点之间通过无向的道路来连接,如果至少两个环公用一条路,路上的游客就会发生冲突;如果一条路不属于任何的环,这条路就没必要修

问,有多少路不必修,有多少路会发生冲突

每一个连通块中,如果边数大于点数,这个块中所有的边全部是冲突边。

所有桥为不需要修建的路。

通过这题学习点的双连通分量怎么求。强连通和双连通的题就做到这吧。

#include <bits/stdc++.h>
using namespace std;

const int M = 200010;
const int N = 10010;

struct Edge {
    int from, to;
    int next;
} edge[M];
int head[N];
int cnt_edge;
void add_edge(int u, int v)
{
    edge[cnt_edge].from = u;
    edge[cnt_edge].to = v;
    edge[cnt_edge].next = head[u];
    head[u] = cnt_edge++;
}

int dfn[N]; int idx;
int low[N];
stack<Edge> stk;
set<int> bcc;
int cut;    // 桥的数量
int ans;    // 冲突边数量
int m, n;

void dfs(int u, int pre)
{
    dfn[u] = low[u] = ++idx;
    for (int i = head[u]; i != -1; i = edge[i].next)
    {
        int v = edge[i].to;
        if (v == pre) continue;
        if (!dfn[v])
        {
            stk.push(edge[i]);
            dfs(v, u);
            low[u] = min(low[u], low[v]);
            if (low[v] >= dfn[u])       // 割点
            {
                Edge tmp;
                int cnt = 0;
                bcc.clear();
                do {
                    cnt++;
                    tmp = stk.top();
                    stk.pop();
                    bcc.insert(tmp.from);
                    bcc.insert(tmp.to);
                } while (tmp.from != u || tmp.to != v);
                if (cnt > bcc.size()) ans += cnt;
            }
            if (low[v] > dfn[u]) ++cut;
        }
        else if (dfn[v] < dfn[u])
        {
            stk.push(edge[i]);
            low[u] = min(low[u], dfn[v]);
        }
    }
}

void init()
{
    memset(head, -1, sizeof head);
    memset(dfn, 0, sizeof dfn);
    ans = cut = cnt_edge = idx = 0;
}

int main()
{
    while (~scanf("%d%d", &n, &m))
    {
        if (n == 0 && m == 0) break;
        int u, v;
        init();
        for (int i = 0; i < m; ++i)
        {
            scanf("%d%d", &u, &v);
            add_edge(u, v);
            add_edge(v, u);
        }
        for (int i = 1; i <= n; ++i)
        if (!dfn[i]) dfs(i, -1);
        printf("%d %d\n", cut, ans);
    }
    return 0;
}

  

posted @ 2015-11-30 20:36  我不吃饼干呀  阅读(985)  评论(1编辑  收藏  举报