1008 Airline Routes (35 分)
解题思路:
强连通分量定义裸题,现学tarjan算法,在基础上面做一点修改——出栈的时候,把出栈的所有点父亲标记为最小根,然后对于每次询问查询其父亲是否相同即可。
代码:
#include<bits/stdc++.h>
#include<unordered_map>
#include<unordered_set>
#define ll long long
#define pii pair<int,int>
#define pll pair<ll,ll>
#define mp make_pair
#define pb push_back
#define G 6.67430*1e-11
#define rd read()
#define pi 3.1415926535
using namespace std;
const ll mod = 1e9 + 7;
const int MAXN = 30000005;
const int MAX2 = 300005;
inline ll read() {
ll x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch>'9') {
if (ch == '-')
f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = (x << 1) + (x << 3) + (ch ^ 48);
ch = getchar();
}
return x * f;
}
ll fpow(ll a, ll b)
{
ll ans = 1;
while (b)
{
if (b & 1)ans = ans * a % mod;
b >>= 1;
a = a * a % mod;
}
return ans;
}
ll gcd(ll a, ll b) { return !b ? a : gcd(b, a % b); }
int n, m;
vector<int> v[20005];
int ins[20005];
int dfn[20005];
int low[20005];
int fa[20005];
int cnt = 0;
stack<int> s;
void tarjan(int e)
{
s.push(e);
dfn[e] = low[e] = ++cnt;
ins[e] = 1;
for (int i = 0; i < v[e].size(); i++)
{
if (!dfn[v[e][i]])
{
tarjan(v[e][i]);
low[e] = min(low[e], low[v[e][i]]);
}
else if (ins[v[e][i]])
{
low[e] = min(low[e], dfn[v[e][i]]);
}
}
if (low[e] == dfn[e])
{
int t;
while (1)
{
t = s.top();
s.pop();
fa[t] = e;
ins[t] = 0;
if (t == e)break;
}
}
}
signed main()
{
int i;
n = rd;
m = rd;
for (int i = 0; i < m; i++)
{
int a = rd, b = rd;
v[a].push_back(b);
}
for (int i = 1; i <= n; i++)
{
if(!low[i])tarjan(i);
}
int p = rd;
while (p--)
{
int a = rd, b = rd;
printf("%s", (fa[a] == fa[b] ? "Yes" : "No"));
if (p)printf("\n");
}
return 0;
}