POJ 1236-Network of Schools(tarjan缩点)

POJ 1236-Network of Schools(tarjan缩点)


传送门qwq:http://poj.org/problem?id=1236

题目大意:

有n(2<=n<=100)个学校,学校之间有单向网络,一个学校在得到软件之后可以顺着单向网络向其他学校传输

输入给出每个学校可以向其他学校传输的传输列表

1.初始时至少几个学校得到该软件才能使得网络内所有学校都收到该软件

2.至少添加几条边,才能使得向网络中任意一个学校发送该软件,最终能传遍网络中每一个学校

思路:

首先,一个学校能传到的所有学校肯定是在一个联通分量里的,首先用一下tarjan进行缩点,缩点之后再统计

根据缩点之后的图的出入度,对于入度为零的点,是需要初始时发送的学校,至于添加的边数,则是出度为零

的点数和入度为零的点数中大的那个

	#include<iostream>
	#include<cstdio>
	#include<cstring>
	#include<vector>
	using namespace std;
	const int N = 109;
	
	int n,t,num,top;
	int dfn[N],low[N],du1[N],du2[N],id[N];
	int Stack[N],instack[N];
	vector<int>q[N];
	
	//tarjan算法,复杂度O(n + m)
	void tarjan(int u)
	{
		dfn[u] = low[u] = ++t;
		Stack[++top] = u;
		instack[u] = 1;
		for(int i = 0; i <q[u].size(); i++){
			int v = q[u][i];
			if(!dfn[v]){
				tarjan(v);
				low[u] = min(low[u],low[v]);
			} else if(instack[v]){
				low[u] = min(low[u],dfn[v]);
			}
		}
		if(dfn[u] == low[u]){//此时出现新的联通分量
			num++;
			int vv;
			do{
				vv = Stack[top--];
				instack[vv] = 0;
				id[vv] = num;//将在一个连通分量中的点缩点
			}while(vv != u);
		}
	} 
	
	int main()
	{
	//	freopen("D:\\test\\in.txt","r+",stdin);
		ios::sync_with_stdio(false);
		cin >> n;
		for(int i = 1; i <= n; i++){
			int x;
			while(cin >> x && x)q[i].push_back(x);
		}
	
		for(int i = 1; i <= n; i++)
			if(!dfn[i])tarjan(i);
	
		if(num == 1) return cout << 1 << endl << 0 << endl,0;//只有1个连通分量时特判
	
		for(int i = 1; i <= n; i++){
			for(int j = 0; j < q[i].size(); j++){
				int v = q[i][j];
				if(id[i] != id[v]){
					du1[id[i]]++;
					du2[id[v]]++;
				}
			}
		}

		int ans1 = 0,ans2 = 0;
		for(int i = 1; i <= num; i++){
			if(du1[i] == 0)ans1++;
			if(du2[i] == 0)ans2++;
		}

		cout << ans2 << endl << max(ans1,ans2) << endl;
		return 0;
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值