题目背景
本场比赛第一题,给个简单的吧,这 100 分先拿着。
题目描述
有n个城市,中间有单向道路连接,消息会沿着道路扩散,现在给出n个城市及其之间的道路,问至少需要在几个城市发布消息才能让这所有n个城市都得到消息。
输入输出格式
输入格式:
第一行两个整数n,m表示n个城市,m条单向道路。
以下m行,每行两个整数b,e表示有一条从b到e的道路,道路可以重复或存在自环。
输出格式:
一行一个整数,表示至少要在几个城市中发布消息。
输入输出样例
输入样例#1: 复制
5 4 1 2 2 1 2 3 5 1
输出样例#1: 复制
2
说明
【数据范围】
对于20%的数据,n≤200;
对于40%的数据,n≤2,000;
对于100%的数据,n≤100,000,m≤500,000.
【限制】
时间限制:1s,内存限制:256M
【注释】
样例中在4,5号城市中发布消息。、
题意:很明显的一个tarjan+缩点,直接套模板,然后输出缩点后入度为0的点的个数,注意在输入的过程中避免成环,应该先来一个判定,其余代码如下
#include<iostream>
using namespace std;
const int maxn = 500010;
int n, m, cnt = 1, a, b, index, sum, total, ans;
int dfn[maxn], low[maxn], belong[maxn], indu[maxn], vis[maxn], Stack[maxn], head[maxn];
struct Node{
int to;
int next;
}node[2 * maxn];
void add(int u, int v) {
node[cnt].to = v;
node[cnt].next = head[u];
head[u] = cnt++;
}
void tarjan(int u) {
dfn[u] = low[u] = ++total;
Stack[++index] = u;
vis[u] = 1;
for (int i = head[u]; i != 0; i = node[i].next) {
int v = node[i].to;
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]) {
++sum;
do {
int p = Stack[index--];
vis[p] = 0;
belong[p] = sum;
} while (Stack[index + 1] != u);
}
}
int main() {
cin >> n >> m;
for (int i = 1; i <= m; i++) {
cin >> a >> b;
if (a != b) add(a, b);
}
for (int i = 1; i <= n; i++) {
if (!dfn[i]) tarjan(i);
}
for (int i = 1; i <= n; i++) {
for (int j = head[i]; j != 0; j = node[j].next) {
int v = node[j].to;
if (belong[v] != belong[i]) {
indu[belong[v]]++;
}
}
}
for (int i = 1; i <= sum; i++) {
if (!indu[i]) ans++;
}
cout << ans << endl;
return 0;
}