HDU - 3394 Railway(连通分量+环)

来源:互联网 发布:mysql和oracle的关系 编辑:程序博客网 时间:2024/05/21 09:41

题目大意:有一个人奇怪的人想要铺路,这个人想把每个环都铺上石头,但是铺石头时不能重复铺,如果重复铺的话,这条边就算损坏
问这个人要损坏多少条边,有多少条边可以不用铺石头

解题思路:不用铺石头的边肯定是桥,因为桥不属于任意一个环
接着判断一下有多少条边会冲突,首先,一个环的话肯定是点-双连通,但点-双连通不一定是个环,所以这个要判断一下。
一个正常的环是要满足 边数=点数 的,如果边数比点数多了,证明这个环被分割成至少三个环了(一个最外围的环,两个被分的小环),可以看出,这三个环每条边都冲突
所以只要满足边数>点数的,都可以证明这个环的所有边冲突

#include <cstdio>#include <cstring>#include <vector>using namespace std;#define N 10010#define M 200010#define min(a,b) ((a) < (b) ? (a): (b))struct Edge{    int from, to, next, id;    Edge() {}    Edge(int from, int to) :from(from), to(to){}}E[M];int n, m, tot, dfs_clock, bnum, bcc_cnt, top;int head[N], pre[N], stack[M], low[N], num[N];vector<int> edge[N];bool vis[N];void AddEdge(int u, int v) {    E[tot].from = u; E[tot].to = v; E[tot].next = head[u]; E[tot].id = tot; head[u] = tot++;    u = u ^ v; v = u ^ v; u = v ^ u;    E[tot].from = u; E[tot].to = v; E[tot].next = head[u]; E[tot].id = tot; head[u] = tot++;}void init() {    memset(head, -1, sizeof(head));    tot = 0;    int u, v;    for (int i = 0; i < m; i++) {        scanf("%d%d", &u, &v);        AddEdge(u, v);    }}void dfs(int u, int fa) {    pre[u] = low[u] = ++dfs_clock;    for (int i = head[u]; i != -1; i = E[i].next) {        int v = E[i].to;        if (!pre[v]) {            stack[++top] = E[i].id;            dfs(v, u);            low[u] = min(low[u], low[v]);            if (low[v] >= pre[u]) {                bcc_cnt++;                edge[bcc_cnt].clear();                int x, id;                while (1) {                    id = stack[top--];                    edge[bcc_cnt].push_back(id);                    x = E[id].from;                    if (x == u)                        break;                }                if (low[v] > pre[u])                     bnum++;            }        }        else if(pre[v] < pre[u] && v != fa) {            low[u] = min(low[u], pre[v]);            stack[++top] = E[i].id;        }    }}void solve() {    memset(pre, 0, sizeof(pre));    dfs_clock = bcc_cnt = bnum = top = 0;    for (int i = 0; i < n; i++)        if (!pre[i])            dfs(i, -1);    int ans = 0;    for (int i = 1; i <= bcc_cnt; i++) {        for (int j = 0; j < n; j++)            vis[j] = false;        int size = edge[i].size(), cnt = 0;        for (int j = 0; j < size; j++) {            if (!vis[E[edge[i][j]].from]) {                vis[E[edge[i][j]].from] = true;                cnt++;            }            if (!vis[E[edge[i][j]].to]) {                vis[E[edge[i][j]].to] = true;                cnt++;            }        }        if (size > cnt)            ans += size;    }    printf("%d %d\n", bnum, ans);}int main() {    while (scanf("%d%d", &n, &m) != EOF && n + m) {        init();        solve();    }    return 0;}
0 0
原创粉丝点击