POJ 3352 Road Construction POJ 3177 Redundant Paths(边双连通图 Tarjan+缩点)

POJ 3352 Road Construction POJ 3177 Redundant Paths(边双连通图 Tarjan+缩点)

ACM

题目地址:

POJ 3352 Road Construction

POJ 3177 Redundant Paths

题意:

问要添加几条边才能使所给无向图图变成边双连通图。

分析:

边连通度:使无向图G不连通的最少删边数量为其边连通度。

边双连通图:边连通度大于1的无向图。

首先缩点,让图变成一个DAG。

现在问题转化为:在树中至少添加多少条边能使图变为双连通图。

若要使得任意一棵树,在增加若干条边后,变成一个双连通图,那么至少增加的边数 =( 这棵树总度数为1的结点数 + 1 )/ 2。

其实就是让树的叶子节点都成对相连,可以在纸上画看看就知道了。

代码:

/*
*  Author:      illuz <iilluzen[at]gmail.com>
*  Blog:        http://blog.csdn.net/hcbbt
*  File:        3352.cpp
*  Create Date: 2014-08-13 15:28:44
*  Descripton:
*/

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <stack>
using namespace std;
#define repf(i,a,b) for(int i=(a);i<=(b);i++)

typedef long long ll;

const int N = 5010;

vector<int> G[N];
bool app[N][N], instack[N];
int n, r, u, v;
int dfn[N], low[N], dg[N], tclock;

void tarjan(int u, int fa) {
	dfn[u] = low[u] = ++tclock;
	instack[u] = 1;

	int sz = G[u].size();
	repf (i, 0, sz - 1) {
		int v = G[u][i];
		if (v == fa)
			continue;
		if (!dfn[v]) {
			tarjan(v, u);
			low[u] = min(low[u], low[v]);
		} else if (instack[v]) {
			low[u] = min(low[u], dfn[v]);
		}
	}
}

void init(int n, int r) {
	memset(app, 0, sizeof(app));
	memset(low, 0, sizeof(low));
	memset(dfn, 0, sizeof(dfn));
	memset(instack, 0, sizeof(instack));
	memset(dg, 0, sizeof(dg));
	repf (i, 1, n) {
		G[i].clear();
	}

	repf (i, 0, r - 1) {
		scanf("%d%d", &u, &v);
		if (!app[u][v]) {
			G[u].push_back(v);
			G[v].push_back(u);
			app[u][v] = app[v][u] = 1;
		}
	}
}

void solve() {
	tarjan(1, -1);
	repf (u, 1, n) {
		int sz = G[u].size();
		repf (i, 0, sz - 1) {
			int v = G[u][i];
			if (low[u] != low[v])
				dg[low[u]]++;
		}
	}

	int cnt = 0;
	repf (i, 1, n) {
		if (dg[i] == 1) {
			cnt++;
		}
	}

	printf("%d\n", (cnt + 1) / 2);
}

int main() {
	while (~scanf("%d%d", &n, &r)) {
		init(n, r);
		solve();
	}
	return 0;
}

POJ 3352 Road Construction POJ 3177 Redundant Paths(边双连通图 Tarjan+缩点)

时间: 2024-10-01 07:55:02

POJ 3352 Road Construction POJ 3177 Redundant Paths(边双连通图 Tarjan+缩点)的相关文章

POJ 3352 Road Construction(添最少边构造边双连通图的结论)

题意:已知无向图,问添加最少的边使之成为边双连通图 思路:显然先缩点成一棵树,添加最少边使一棵树的边双连通 此处有结论:对于一棵树添加(1+leaf)>>1 条无向边就能构造成一个双连通图,构造方法显然(脑补一下 //216K 63MS C++ 1754B #include<cstdio> #include<iostream> #include<cstring> #include<algorithm> using namespace std; c

Poj 3352 Road Construction &amp; Poj 3177 Redundant Paths(边双连通分量+缩点)

Road Construction Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 9465   Accepted: 4699 Description It's almost summer time, and that means that it's almost summer construction time! This year, the good people who are in charge of the ro

POJ 3352 Road Construction&amp;&amp; POJ 3177 Redundant Paths 双联通分量

大意:给定n点,和m条边的关系图中的一些边随时可能施工导致不能够通过,所以至少加多少条边才能够使得途中任意两条边联通? 思路:很明显只要图中的任意两点都是两条边来链接即可.那么我们可以先缩点构建新图,然后统计出度为1的点的个数ans,那么需要加的边数就是(ans+1)/2条; (PS;因为建图是双向的图所以,在Tarjan缩点的时候就需要遇到临边便越过,并且判断是不是同一个联通分支用num比较!) #include<map> #include<queue> #include<

POJ 3177 Redundant Paths POJ 3352 Road Construction(双连通)

POJ 3177 Redundant Paths POJ 3352 Road Construction 题目链接 题意:两题一样的,一份代码能交,给定一个连通无向图,问加几条边能使得图变成一个双连通图 思路:先求双连通,缩点后,计算入度为1的个数,然后(个数 + 1) / 2 就是答案(这题由于是只有一个连通块所以可以这么搞,如果有多个,就不能这样搞了) 代码: #include <cstdio> #include <cstring> #include <algorithm&

POJ 3352 Road Construction(图论-tarjan)

Road Construction Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 8647   Accepted: 4318 Description It's almost summer time, and that means that it's almost summer construction time! This year, the good people who are in charge of the ro

POJ 3352 Road Construction 使得无向图边变双连通图

点击打开链接 Road Construction Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 8168   Accepted: 4106 Description It's almost summer time, and that means that it's almost summer construction time! This year, the good people who are in charge of

POJ - 3352 Road Construction(边双连通分支)

1.给定一个连通的无向图G,至少要添加几条边,才能使其变为双连通图. 2.POJ - 3177 Redundant Paths(边双连通分支)(模板)  与这道题一模一样.代码就改了下范围,其他都没动... 3. //边双连通分支 /* 去掉桥,其余的连通分支就是边双连通分支了.一个有桥的连通图要变成边双连通图的话, 把双连通子图收缩为一个点,形成一颗树.需要加的边为(leaf+1)/2(leaf为叶子结点的个数) POJ 3177 给定一个连通的无向图G,至少要添加几条边,才能使其变为双连通图

POJ 3177 Redundant Paths (双连通)

题目地址:POJ 3177 找出各个双连通分量度数为1的点,然后作为叶子节点,那么ans=(叶子结点数+1)/2.需要注意的是有重边. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.h> #include <map> #include

POJ 3352 Road Construction(边—双连通分量)

http://poj.org/problem?id=3352 题意: 给出一个图,求最少要加多少条边,能把该图变成边—双连通. 思路:双连通分量是没有桥的,dfs一遍,计算出每个结点的low值,如果相等,说明属于同一个双连通分量. 接下来把连通分量缩点,然后把这些点连边. 对于一棵无向树,我们要使得其变成边双连通图,需要添加的边数 == (树中度数为1的点的个数+1)/2. 1 #include<iostream> 2 #include<algorithm> 3 #include&