码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2015-08-14 06:33:42      阅读:194      评论:0      收藏:0      [点我收藏+]

标签:

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

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

#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;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

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

标签:

原文地址:http://blog.csdn.net/l123012013048/article/details/47633881

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!