USACO5.3.3 Network of Schools (schlnet)

先用tarjan缩点。
第一问的解就是缩点后所有没有入度的点,因为没有学校给会它们传软件,它们必须要接受新软件副本。
第二问的解没有入度与没有出度的点个数较多的数目。因为所有没有入度的点必须给它一条入边,没有出度的点必须给它一条出边。
这题还须要特判,如果缩点后只有一个点,则输出1,0
/*
ID:shijiey1
LANG:C++
PROG:schlnet
*/
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <stack>
#include <vector>

using namespace std;

int V;
vector<int> edges[105];
stack<int> s;
int vis[105];
int dfn[105];
int low[105];
int cnt = 0;
int num = 0;
int color[105];
int tree[105][105];
int in[105];
int out[105];
void tarjan(int u) {
	s.push(u);
	vis[u] = 1;
	cnt++;
	dfn[u] = low[u] = cnt;

	for (int i = 0; i < edges[u].size(); i++) {
		int v = edges[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 (low[u] == dfn[u]) {
		int t;
		num++;
		do {
			t = s.top();
			color[t] = num;
			s.pop();
			vis[t] = 0;
		} while (t != u);
	}

}

int main() {
	freopen("schlnet.in", "r", stdin);
	freopen("schlnet.out", "w", stdout);
	scanf("%d", &V);
	int t;
	for (int i = 1; i <= V; i++) {
		while(cin >> t) {
			if (!t) break;
			edges[i].push_back(t);
		}
	}
	for (int i = 1; i <= V; i++) {
		if (!dfn[i]) tarjan(i);
	}
	
	for (int i = 1; i <= V; i++) {
		for (int j = 0; j < edges[i].size(); j++) {
			if (color[i] == color[edges[i][j]]) continue;
			if (tree[color[i]][color[edges[i][j]]]) continue;
			tree[color[i]][color[edges[i][j]]] = 1;
			in[color[edges[i][j]]]++;
			out[color[i]]++;
		}
	}
	if (num == 1) cout << 1 << endl << 0 << endl;
	else {
		int ans1 = 0, ans2 = 0;
		for (int i = 1; i <= num; i++) {
			if (!in[i]) ans1++;
			if (!out[i]) ans2++;
		}
		cout << ans1 << endl << max(ans1, ans2) << endl;
	}
	
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值