【原题】
【题目翻译】
有n个城市和m条道路,每条道路都是单向的,给你一个城市s,求最少添加多少条道路可使s到达所有其他城市。
【输入格式】
第一行有三个整数为n,m,s,为城市的数量、道路的数量和你的出发点
以下m行为道路i,每行输入Ui和Vi,表示城市Ui能通向Vi
(1≤n≤5000,0≤m≤5000,1≤s≤n,1≤Ui,Vi≤n,Ui≠Vi)
【输出格式】
输出一个数,表示你需要添加的最小道路数使得城市s可到达所有城市,如果不需要添加,请输出0
S a m p l e I n p u t Sample~~Input Sample Input
9 9 1
1 2
1 3
2 3
1 5
5 6
6 1
1 8
9 8
7 1
S a m p l e O u t p u t Sample~~Output Sample Output
3
【题意分析】
可以互相到达的城市看做一个连通块
很naive跑一遍tarjan缩点,统计出入度为0的连通块个数就是答案(因为入度为0的连通块需要道路)
如果首都是在一个入度为0的连通块里,那么答案要减去一。
因为假设首都所在连通块为u,和首都联通的连通块为v
u,v两个连通块,统计了2个答案,但实际只要u->v一条边就行了
Code:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
#define MAXN 1000010
using namespace std;
struct fls {
int to, next;
}edge[MAXN];
int head[MAXN], stack[MAXN], dfn[MAXN], low[MAXN], DAG[MAXN];
int deg[MAXN], vis[MAXN], n, m, capital, ans, cnt, idx, top, tot_circle;
inline int read () {
register int s = 0, w = 1;
register char ch = getchar ();
while (! isdigit (ch)) {if (ch == '-') w = -1; ch = getchar ();}
while (isdigit (ch)) {s = (s << 3) + (s << 1) + (ch ^ 48); ch = getchar ();}
return s * w;
}
inline void connect (int u, int v) {
edge[++cnt].to = v, edge[cnt].next = head[u], head[u] = cnt;
}
void tarjan (int now) {
dfn[now] = low[now] = ++idx;
vis[now] = 1, stack[++top] = now;
for (register int i = head[now]; i; i = edge[i].next) {
int v = edge[i].to;
if (! dfn[v]) {
tarjan (v);
low[now] = min (low[now], low[v]);
}else if (vis[v]) low[now] = min (low[now], low[v]);
}
if (dfn[now] == low[now]) {
tot_circle++;
while (int y = stack[top--]) {
DAG[y] = tot_circle;
vis[y] = 0;
if (now == y) break;
}
}
}
int main () {
n = read (), m = read (), capital = read ();
for (register int i = 1; i <= m; i++) {
int u = read (), v = read ();
connect (u, v);
}
for (register int i = 1; i <= n; i++)
if (! dfn[i]) tarjan (i);
for (register int i = 1; i <= n; i++)
for (register int j = head[i]; j; j = edge[j].next) {
int v = edge[j].to;
if (DAG[i] != DAG[v]) deg[DAG[v]]++;
}
for (register int i = 1; i <= tot_circle; i++)
if (! deg[i]) ans++;
if (! deg[DAG[capital]]) ans--;
printf ("%d\n", ans);
return 0;
}