列表

详情


NC50393. 网络协议

描述

一些学校连接在一个计算机网络上。学校之间存在软件支援协议。每个学校都有它应支援的学校名单(学校a支援学校b,并不表示学校b一定支援学校a)。当某校获得一个新软件时,无论是直接得到还是网络得到,该校都应立即将这个软件通过网络传送给它应支援的学校。因此,一个新软件若想让所有连接在网络上的学校都能使用,只需将其提供给一些学校即可。
任务
  1. 请编一个程序,根据学校间支援协议(各个学校的支援名单),计算最少需要将一个新软件直接提供给多少个学校,才能使软件通过网络被传送到所有学校;
  2. 如果允许在原有支援协议上添加新的支援关系。则总可以形成一个新的协议,使得此时只需将一个新软件提供给任何一个学校,其他所有学校就都可以通过网络获得该软件。编程计算最少需要添加几条新的支援关系。

输入描述

第一行是一个正整数n,表示与网络连接的学校总数。随后n行分别表示每个学校要支援的学校,即:i+1行表示第i号学校要支援的所有学校代号,最后0结束。
如果一个学校不支援任何其他学校,相应行则会有一个0。一行中若有多个数字,数字之间以一个空格分隔。

输出描述

包含两行,第一行是一个正整数,表示任务a的解,第二行也是一个正整数,表示任务b的解。

示例1

输入:

5
2 4 3 0
4 5 0
0
0
1 0

输出:

1
2

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 4ms, 内存消耗: 504K, 提交时间: 2020-01-05 17:34:52

#include<bits/stdc++.h>
using namespace std;

const int MAXN = 128;

int N;
vector<int> G[MAXN];
vector<int> rG[MAXN];
bool vis[MAXN];
int scc[MAXN];
int scc_cnt;
vector<int> path;

vector<int> g[MAXN];
int indeg[MAXN];
int outdeg[MAXN];

void dfs(int s) {
  vis[s] = true;
  for (auto t: G[s]) if (!vis[t]) dfs(t);
  path.push_back(s);
}

void rdfs(int s) {
  scc[s] = scc_cnt;
  for (auto t: rG[s]) if (!scc[t]) rdfs(t);
}

void Kosaraju() {
  for (int i = 1; i <= N; i++) if (!vis[i]) dfs(i);
  reverse(path.begin(), path.end());
  for (auto i: path) if (!scc[i]) scc_cnt++, rdfs(i);
}

int main() {
  cin >> N;
  for (int s = 1; s <= N; s++) {
    int t;
    while (cin >> t && t) G[s].push_back(t), rG[t].push_back(s);
  }
  Kosaraju();
  for (int s = 1; s <= N; s++) {
    for (auto t: G[s]) if (scc[s] != scc[t]) g[scc[s]].push_back(scc[t]);
  }
  // for (int s = 1; s <= N; s++) cout << scc[s] << " "; cout << endl;
  for (auto s = 1; s <= scc_cnt; s++) {
    for (auto t: g[s]) indeg[t]++;
    for (auto t: g[s]) outdeg[s]++;
  }
  int ans_a = count(indeg+1, indeg+scc_cnt+1, 0);
  int ans_b = scc_cnt == 1? 0: max(int(count(outdeg+1, outdeg+scc_cnt+1, 0)), ans_a);
  cout << ans_a << endl;
  cout << ans_b << endl;
}

C++ 解法, 执行用时: 4ms, 内存消耗: 428K, 提交时间: 2022-02-15 21:06:32

#include<bits/stdc++.h>
using namespace std;
int n,s[101],d,group[101],cnt;
bool vis[101],in[101],out[101];
vector <int> g[2][101];
void kosaraju(const int &x){
	vis[x] = 1;
	for (int i = 0;i < g[0][x].size();i++)
		if (!vis[g[0][x][i]])
			kosaraju(g[0][x][i]);
	s[++d] = x;
}
void rkosaraju(const int &x){
	group[x] = cnt;
	vis[x] = 0;
	for (int i = 0;i < g[1][x].size();i++)
		if (vis[g[1][x][i]])
			rkosaraju(g[1][x][i]);
}
int main(){
	cin>>n;
	int x,y,i,j;
	for (i = 1;i <= n;i++)
		while (cin>>x){
			if (!x)break;
			g[0][i].push_back(x);
			g[1][x].push_back(i);
		}
	for (i = 1;i <= n;i++)
		if (!vis[i])
			kosaraju(i);
	for (i = d;i;i--)
		if (vis[s[i]]){
			cnt++;
			rkosaraju(s[i]);
		}
	for (i = 1;i <= n;i++)
		for (j = 0;j < g[0][i].size();j++)
			if (group[i] != group[g[0][i][j]]){
				in[group[g[0][i][j]]] = 1;
				out[group[i]] = 1;
			}
	if (cnt == 1){
		cout<<"1\n0";
		return 0;
	}
	x = 0;
	y = 0;
	for (i = 1;i <= cnt;i++){
		if (!in[i])x++;
		if (!out[i])y++;
	}
	cout<<x<<endl<<max(x,y);
	return 0;
}

上一题