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

HDU 3394 Railway 【点双联通】

2018-02-24 14:51 369 查看
传送门

// 有一个公园有n个景点,公园的管理员准备修建m条道路,并且安排一些形成回路的参观路线。如果一条道路被多条道路公用,那么这条路是冲突的;如果一条道路没在任何一个回路内,那么这条路是不冲突的

问分别有多少条有冲突的路和没有冲突的路

思路: 如果某条边有冲突, 那么它至少存在于两个环中, 也就是我们要判断图中的环, 其边于点的关系:

边数 = 点数 : 一个环

边数 > 点数 : >一个环

边数 < 点数 : 一个线段, 即桥. 也就是不冲突的路

AC Code

const int maxn = 1e4 + 5;
int cas=1;
int dfn[maxn], low[maxn], cut[maxn];
int n, m;
int cnt, head[maxn];
int dfs_id, cut_num;
int vis[maxn];
stack<int >st;
struct node
{
int from, to, next;
}e[maxn*20];

void add(int u, int v)
{
e[cnt] = node{u, v, head[u]};
head[u] = cnt++;
}
int ans1, ans2;
void init()
{
Fill(dfn, 0); Fill(low, 0); Fill(cut, 0);
cnt = 0; Fill(head, -1);
dfs_id = cut_num = 0;
ans1 = ans2 = 0;
}
void tarjan(int u,int fa)
{
int son = 0;
dfn[u] = low[u] = ++dfs_id;
for(int i = head[u] ; ~i ; i = e[i].next) {
int v = e[i].to;
if(v == fa) continue;
if(!dfn[v]){
son++;
st.push(i);  //把边的编号推进去.
tarjan(v, u);
low[u] = min(low[u], low[v]);
if(low[v] >= dfn[u]){
cut[u] = 1; Fill(vis, 0);
int c1 = 0, c2 = 0;
while (1) {
int id = st.top(); st.pop();
if (!vis[e[id].from]) c1++;
if (!vis[e[id].to]) c1++;
vis[e[id].from] = vis[e[id].to] = 1;
c2++;
if (e[id].from == u && e[id].to == v) {
if (c1 > c2) ans1++;
if (c1 < c2) ans2 += c2;
break;
}
}
}
}
else if(dfn[v] < dfn[u]){
st.push(i);
low[u] = min(low[u],dfn[v]);
}
}
if (fa == -1 && son > 1) cut[u] = 1;
}

void solve()
{
while(~scanf("%d%d", &n, &m)){
if (n + m == 0) break;
init();
for (int i = 1 ; i <= m ; i ++) {
int u, v;
scanf("%d%d", &u, &v);
add(u, v); add(v, u);
}
for(int i = 1 ; i <= n ; i ++) {
if(!dfn[i]) tarjan(i, -1);
}
printf("%d %d\n", ans1, ans2);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: