设为首页 加入收藏

TOP

HDU - 3394 Railway(连通分量+环)
2015-11-21 00:54:42 来源: 作者: 【 】 浏览:1
Tags:HDU 3394 Railway 连通 分量

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

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

#include 
   
     #include 
    
      #include 
     
       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
      
        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 , bnum, ans); } int main() { while (scanf(%d%d, &n, &m) != EOF && n + m) { init(); solve(); } return 0; } 
      
     
    
   

?

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇HDU 4265(Science!-二分网络流) 下一篇HDU - 2460 Network(桥+LCA)

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: