poj1236 Network of Schools(tarjan缩点)

本文介绍了一个关于学校网络传输的问题解决方法。利用Tarjan算法寻找强连通分量并进行缩点,进而求解有向无环图(DAG)中的入度与出度,最终确定最少软件备份数量及所需添加边数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:一些学校连成了网络, 在学校之间存在某个协议:每个学校都维护一张传送表,表明他们要负责将收到的软件传送到表中的所有学校。如果A在B的表中,那么B不一定在A的表中。现在的任务就是,给出所有学校及他们维护的表,问1、如果所有学校都要被传送到,那么需要几份软件备份;2、如果只用一份软件备份,那么需要添加几条边?

思路:先使用tarjan算法找强连通分量,并进行缩点。对于缩点后的图,求每个点的入度和出度,第1问就是图中入度为0的点的个数,而第2问则是入度为0的点的个数和出度为0的点的个数这两者中较大的那一个。(参考DAG性质:对于一个有向无环图,若想让它成为强连通图,至少需要添加max(a,b) a为入度为0的边点的数量,b为出度为0的点的数量

代码:

#include <iostream>
#include <fstream>
#include <vector>
#include <stack>
#include <algorithm>
#define MAXN 105
using namespace std;

vector<int> node[MAXN];
stack<int> S;
int DFN[MAXN], LOW[MAXN], belong[MAXN], out[MAXN], in[MAXN];
bool vis[MAXN];
int tot;
int cnt;

void tarjan(int u)
{
	int v;
	DFN[u] = LOW[u] = ++tot;
	S.push(u);
	vis[u] = 1;
	for (int i = 0; i < node[u].size(); i++)
	{
		v = node[u][i];
		if (!DFN[v])
		{
			tarjan(v);
			LOW[u] = min(LOW[u], LOW[v]);
		}
		else if(vis[v])
			LOW[u] = min(LOW[u], DFN[v]);
	}
	if (DFN[u] == LOW[u])
	{
		cnt++;
		do {
			v = S.top();
			S.pop();
			vis[v] = 0;
			belong[v] = cnt;
		} while (v != u);
	}
}

int main()
{
	//fstream cin("test.txt");
	int n, ans1, ans2;
	ans1 = ans2 = 0;
	cin >> n;
	for (int i = 1; i <= n; i++)
	{
		int to;
		while (cin >> to, to)
			node[i].push_back(to);
	}
	for (int i = 1; i <= n; i++)
	{
		if (!DFN[i])
			tarjan(i);
	}
	for (int i = 1; i <= n; i++)
		for (int j = 0; j < node[i].size(); j++)
		{
			//计算出度
			if (belong[i] != belong[node[i][j]])
			{
				out[belong[i]]++;
				in[belong[node[i][j]]]++;
			}		
		}
	for (int i = 1; i <= cnt; i++)
	{
		if (in[i] == 0)
			ans1++;
		if (out[i]== 0)
			ans2++;
	}
	if (cnt == 1)
		cout << 1 << endl << 0 << endl;
	else
	{
		cout << ans1 << endl;
		cout << max(ans1, ans2) << endl;
	}
	//system("pause");
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值