您的位置:首页 > 大数据 > 人工智能

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

2015-11-30 20:36 411 查看
一个公园中有 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
;
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
; int idx;
int low
;
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;
}


  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: