UVA 11504 - Dominos(强连通分量)

UVA 11504 - Dominos

题目链接

题意:给定一个多米诺骨牌的有向图,为最多要推几个才能全倒

思路:强连通分量,缩点后找出度数为0的点就是答案

代码:

#include <cstdio>
#include <cstring>
#include <vector>
#include <stack>
#include <algorithm>
using namespace std;

const int N = 100005;

vector<int> g[N], scc[N];
int pre[N], lowlink[N], sccno[N], dfs_clock, scc_cnt;
stack<int> S;

void dfs_scc(int u) {
	pre[u] = lowlink[u] = ++dfs_clock;
	S.push(u);
	for (int i = 0; i < g[u].size(); i++) {
		int v = g[u][i];
		if (!pre[v]) {
			dfs_scc(v);
			lowlink[u] = min(lowlink[u], lowlink[v]);
		} else if (!sccno[v])
			lowlink[u] = min(lowlink[u], pre[v]);
	}
	if (lowlink[u] == pre[u]) {
		scc_cnt++;
		while (1) {
			int x = S.top(); S.pop();
			sccno[x] = scc_cnt;
			if (x == u) break;
		}
	}
}

void find_scc(int n) {
	dfs_clock = scc_cnt = 0;
	memset(sccno, 0, sizeof(sccno));
	memset(pre, 0, sizeof(pre));
	for (int i = 0; i < n; i++)
		if (!pre[i]) dfs_scc(i);
}

int in[N];
int t, n, m, u[N], v[N];

int main() {
	scanf("%d", &t);
	while (t--) {
		scanf("%d%d", &n, &m);
		for (int i = 0; i < n; i++)
			g[i].clear();
		for (int i = 0; i < m; i++) {
			scanf("%d%d", &u[i], &v[i]);
			u[i]--; v[i]--;
			g[u[i]].push_back(v[i]);
		}
		find_scc(n);
		memset(in, 0, sizeof(in));
		for (int i = 0; i < m; i++) {
			if (sccno[u[i]] != sccno[v[i]])
				in[sccno[v[i]]]++;
		}
		int ans = 0;
		for (int i = 1; i <= scc_cnt; i++)
			if (in[i] == 0) ans++;
		printf("%d\n", ans);
	}
	return 0;
}
时间: 2024-12-29 11:36:06

UVA 11504 - Dominos(强连通分量)的相关文章

UVa 11504 - Dominos

题目:有一些多米诺骨牌,现在告诉你他们的相邻顺序,问最少推几次可以把他们全部推倒. 分析:图论,强连通分量.强连通分量上的某点被推到,整个分量都会倒. 求强连通分量,然后缩点,剩下的"点"中每个入度为0的点都要用手推倒:(必要性) 再者,在缩点后的图中,每次找到一个入度为0的点推倒后,不会产生新的入度为0的点:(充分性) (新产生的入度为0的点,之前入度一定不为0,那么它的前驱倒下后,他也必然倒下,不会留下来) 综上,要推倒所有入度为0的点,所有点就倒下了. 说明:注意是有向图. #i

UVA 12167 - Proving Equivalences(强连通分量+缩点)

UVA 12167 - Proving Equivalences 题目链接 题意:给定一些已经存在的等价性证明,要求全部等价,需要在多最少几次证明 思路:先求出强连通分量,然后进行缩点,在缩点后的图上统计入度和出度为0结点的最大值,就是需要加的边数,注意如果整个图已经是强连通,就直接是答案 代码: #include <cstdio> #include <cstring> #include <vector> #include <stack> #include

UVA 11324 The Largest Clique (强连通分量缩点,图DP)

题目: http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=25&page=show_problem&problem=2299 题意: 给你一个有向图,求一个点集合的最大大小,使得此点集合中对于任意点对(u,v),有从u到v或者从v到u的边 方法: 先找强连通分量缩点,每个强连通分量显然满足条件,然后在缩点后的图中找到一条权值最大的路径,权值为此路径的点权之和,点权为这个

uva 11324 The Largest Clique(强连通分量缩点+DAG动态规划)

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=25&page=show_problem&problem=2299 题意:输入n和m,有n个点和m条有向边,求出一个节点集合包括的节点个数最多,而且该节点内的不论什么两点a,b,要么a能到达b,要么b能到达a,要么a和b互相到达. 思路:强连通分量缩点形成有向无环图DAG,把缩点后的每一个点的权值置为该强连通分量的节点个

UVA 11324 - The Largest Clique(强连通分量+缩点)

UVA 11324 - The Largest Clique 题目链接 题意:给定一个有向图,要求找一个集合,使得集合内任意两点(u, v)要么u能到v,要么v能到u,问最大能选几个点 思路:强连通分量,构造出scc之后,缩点,每个点的权值是集合点个数,然后做一遍dag找出最大权值路径即可 代码: #include <cstdio> #include <cstring> #include <vector> #include <stack> #include

UVA - 11324 The Largest Clique (DAG + 强连通分量)

题目大意:给出一张有向图G,求一个结点数最大的结点集,使得该点集中任意两个结点u和v满足: 要么u可到达v,要么v可以到达u(u和v互相可达也可以) 解题思路:u和v相互可达的时候,就是两个结点在同一个强连通分量内的时候 首先要保证集合里面的点可达:强连通分量就满足集合内的点都相互可达.所以第一件事就是找出所有的强连通分量,并统计出每个强连通分量内的结点数 然后找出每个强连通分量之间的关系,也就是找出两个强连通分量之间的桥,连接可连接的强连通分量 最后将每个强连通分量收缩,得到SCC图.此时的S

UVA - 11709 Trust groups (强连通分量)

链接 :  http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=28292 求强连通分量的个数. #pragma comment(linker, "/STACK:10240000,10240000") #include <algorithm> #include <iostream> #include <sstream> #include <cstring> #incl

UVa 11324 The Largest Clique (强连通分量+DP)

题意:给定一个有向图,求一个最大的结点集,使得任意两个结点,要么 u 能到 v,要么 v 到u. 析:首先,如果是同一个连通分量,那么要么全选,要么全不选,然后我们就可以先把强连通分量先求出来,然后缩成一个点,然后该图就成了一个DAG,然后就可以直接用DP来做了. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <string> #i

UVA 1324 The Largest Clique 最大团(强连通分量,变形)

题意:给一个有向图,要求找出一些点,使得这些点中的任意点对,要么可以互通,要么单向可达. 思路:最低只要求单向可达即可,即a->b都可以算进去. 强连通分量内的点肯定是满足要求的,可以全选,但是有多个强连通分量时就不行了,得有取舍.老方法,先缩点,缩完点后是没有环的存在的,所以就是拓扑图了.如果只给一个拓扑图,要求找一条链使得链上的点最多,那么可以用判断拓扑的方式,逐个将入度为0的点删除,且在删除的时候记录下最多有多少个点,删到最后一个点时就出结果了.这样的方法同样适用,只是每个点可能是缩点,而