A. Environment-Friendly Travel
注意到\(N*B\)很小,所以我們利用這個作為狀態跑\(dp\)就行。時間復雜度為\(O(10^8)\)左右。
比較套路的\(dp\)了。
Code
/*
* Author: heyuhhh
* Created Time: 2020/5/21 16:59:22
*/
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
#define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
void err() { std::cout << std::endl; }
template<typename T, typename...Args>
void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
template <template<typename...> class T, typename t, typename... A>
void err(const T <t> &arg, const A&... args) {
for (auto &v : arg) std::cout << v << ' '; err(args...); }
#else
#define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int maxN = 1000 + 5, maxM = 105, MAX = 20005;
int T, N, B;
int c[maxN];
int cost[maxN][maxN], w[maxN][maxN];
struct Point {
int x, y;
}p[maxN];
int distance(int i, int j) {
return (int)ceil(hypot(p[i].x - p[j].x, p[i].y - p[j].y) - 1e-9);
}
int dis[maxN][maxM];
struct Dijkstra{
struct node{
int val, d, u;
bool operator < (const node &A) const {
return val > A.val;
}
};
bool vis[maxN][maxM];
void dij(int s) {
priority_queue <node> q;
memset(dis, INF, sizeof(dis));
memset(vis, 0, sizeof(vis));
dis[s][0] = 0;
q.push(node{0, 0, 0});
while(!q.empty()) {
node cur = q.top(); q.pop();
int u = cur.u, d = cur.d;
if(vis[u][d]) continue;
vis[u][d] = 1;
for (int v = 0; v <= N + 1; v++) {
int dist = w[u][v];
if (d + dist > B) continue;
if(dis[v][d + dist] > dis[u][d] + cost[u][v]) {
dis[v][d + dist] = dis[u][d] + cost[u][v];
q.push(node{dis[v][d + dist], d + dist, v});
}
}
}
}
}solver;
void run() {
cin >> p[0].x >> p[0].y;
int ex, ey; cin >> ex >> ey;
cin >> B >> c[0] >> T;
for (int i = 1; i <= T; i++) {
cin >> c[i];
}
cin >> N;
vector <pair<int, pii>> edges;
for (int i = 1; i <= N; i++) {
cin >> p[i].x >> p[i].y;
int k; cin >> k;
while (k--) {
int j, t; cin >> j >> t; ++j;
edges.push_back(MP(i, MP(j, t)));
}
}
p[N + 1] = Point{ex, ey};
for (int i = 0; i <= N + 1; i++) {
for (int j = 0; j <= N + 1; j++) {
w[i][j] = distance(i, j);
}
}
memset(cost, INF, sizeof(cost));
for (int i = 1; i <= N; i++) {
cost[0][i] = c[0] * w[0][i];
cost[i][N + 1] = c[0] * w[i][N + 1];
}
cost[0][N + 1] = c[0] * w[0][N + 1];
for (auto it : edges) {
int i = it.fi;
int j = it.se.fi, t = it.se.se;
cost[i][j] = cost[j][i] = min(cost[i][j], c[t] * w[i][j]);
}
solver.dij(0);
int ans = INF;
for (int i = 0; i <= B; i++) {
ans = min(ans, dis[N + 1][i]);
}
if (ans == INF) ans = -1;
cout << ans << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cout << fixed << setprecision(20);
run();
return 0;
}
B. Biodiversity
簽到。
Code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef long double ld;
const int MAXN = 1e6 + 5, MAXM = 4e5 + 5, BOUND = 2e5, MOD = 998244353, INF = 0x3f3f3f3f, base = 10000;
const int inv2 = (MOD + 1) >> 1;
const ll INFL = 0x3f3f3f3f3f3f3f3f;
const double PI = acos(-1.0), eps = 1e-9;
#define lson o<<1,l,m
#define rson o<<1|1,m+1,r
#define lc(x) ch[x][0]
#define pii pair<int,int>
#define vi vector<int>
#define vii vector<pair<int,int>>
#define rc(x) ch[x][1]
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define all(a) (a).begin(), (a).end()
#define sz(a) int(a.size())
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define fi first
#define se second
#define MP std::make_pair
#define ri register int
//#define sz(a) int((a).size())
const int N = 2e5,M = (1<<20);
inline int add(int a, int b) {return a + b >= MOD ? a + b - MOD : a + b;}
inline int dec(int a, int b) {return a < b ? a - b + MOD : a - b;}
inline int mul(int a, int b) {return 1ll * a * b % MOD;}
template <typename T>
inline void cmin(T &a,T b){a = min(a,b);}
template <typename T>
inline void cmax(T &a,T b){a = max(a,b);}
ll qpow(ll a,ll b){
ll ans=1;
for(;b;b>>=1,a=a*a%MOD)if(b&1)ans=ans*a%MOD;
return ans;
}
mt19937 mrand(random_device{}());
map<string,int> mp;
void run(){
int n; cin>>n;
string tmp;
rep(i,1,n)cin>>tmp,mp[tmp]++;
int mx=0;
string ans;
for(auto &e:mp){
if(e.second > mx){
mx = e.second;
ans = e.first;
}
}
if(mx > n-mx){
cout<<ans<<'\n';
}else cout<<"NONE\n";
}
int main() {
ios::sync_with_stdio(false); cin.tie(0);
int _=1;
while(_--)run();
return 0;
}
C. Ants
直接枚舉就行,很大的數沒什么用。
Code
/*
* Author: heyuhhh
* Created Time: 2020/5/21 13:45:08
*/
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
#define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
void err() { std::cout << std::endl; }
template<typename T, typename...Args>
void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
template <template<typename...> class T, typename t, typename... A>
void err(const T <t> &arg, const A&... args) {
for (auto &v : arg) std::cout << v << ' '; err(args...); }
#else
#define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e6 + 5;
void run() {
int n; cin >> n;
vector <int> a;
for (int i = 1; i <= n; i++) {
string s; cin >> s;
int len = s.length();
if (s[0] == '-' || len > 100) continue;
if (len < 9) {
int x = 0;
for (int j = 0; j < len; j++) {
x = x * 10 + s[j] - '0';
}
a.push_back(x);
}
}
sort(all(a));
for (int i = 0, j = 0;; i++, j++) {
if (j >= sz(a) || i != a[j]) {
cout << i << '\n';
return;
}
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cout << fixed << setprecision(20);
run();
return 0;
}
F. Icebergs
模擬一下。
Code
#include<cstdio>
#include<cmath>
#define REP(i,a,b) for(int i=(a); i<(b); i++)
#define REPE(i,a,b) for(int i=(a); i<=(b); i++)
using namespace std;
#define D Point
#define CD const D
struct D { double x,y;};
double cross(CD&l, CD&r) {return l.x*r.y-l.y*r.x;}
template<class T, int Z>
struct Arr {
T data[Z]; int n;
Arr() :n(0) {}
T&operator[](int z) {return data[z];}
void push(const T&x) {data[n++]=x;}
void pop() {n--;}
};
typedef Arr<D,57> Plg;
/*void tubao(Plg &p, Plg &ch) {
sort(p.data,p.data+p.n);
int &m=ch.n; m=0;
REP(i,0,p.n) {
while(m>1 && cross(ch[m-1]-ch[m-2], p[i]-ch[m-2])<=0 ) m--;
ch[m++]=p[i];
}
int k=m;
PERE(i,p.n-2,0) {
while(m>k && cross(ch[m-1]-ch[m-2], p[i]-ch[m-2])<=0) m--;
ch[m++]=p[i];
}
if(p.n>1) m--;
}*/
double area(Plg &p) {
double ans=0;
REP(i,0,p.n) {
ans+=cross(p[i], p[(i+1)%p.n]);;
}
return fabs(ans/2);
}
#undef D
#undef CD
Plg p;
int main() {
int n; scanf("%d", &n);
double ans=0;
while(0<n--) {
scanf("%d", &p.n);
for(int i=0; i<p.n; i++) {
scanf("%lf%lf", &p[i].x, &p[i].y);
}
ans+=area(p);
}
printf("%.0lf\n", floor(ans));
return 0;
}
G. Swapping Places
題意:
給定\(s,s\leq 200\)種物品,給定\(l,l\leq 10000\)組關系,若關系中的兩種物品相鄰那么就可以交換。
給定長度為\(n\)的序列,每個位置上面為一種物品,現在要求出字典序最小的最終序列。
思路:
我們可以思考一下貪心的做法:
- 考慮依次確定\(1,2,...,n\)位置上面的數,確定位置\(i\)時,我們貪心將字典序最小的物品往前面移動,最終\(i\)位置上面的數即是最終答案。
簡單說一下貪心做法的正確性,我們每一輪優先移動字典序最小的,如果沒能到達\(i\),那么當前物種必然不可能位於位置\(i\)。
但以上的思想可能復雜度不對or碼量較大。
因為我們目前的做法是從后往前,我們可以考慮從前往后,為每種物品給定一個最優位置。那么我們還是按字典序最小的來,我們每次將最優匹配指針往后移動直至不能移動,若當前指針指向的位置為當前物品,那么此時等價於將其往前面移動能夠成功到\(i\),所以就確定了答案。
從后往前的話可能會對每一種物品涉及到多個指針,每次取出第一個指針往前移動。但我們可以讓這些指針保持不變,用一個指針從前往后移動,這樣碼量上會好很多。
很巧妙的做法。
Code
/*
* Author: heyuhhh
* Created Time: 2020/5/22 10:52:27
*/
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
#define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
void err() { std::cout << std::endl; }
template<typename T, typename...Args>
void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
template <template<typename...> class T, typename t, typename... A>
void err(const T <t> &arg, const A&... args) {
for (auto &v : arg) std::cout << v << ' '; err(args...); }
#else
#define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e5 + 5;
void run() {
int s, l, n;
cin >> s >> l >> n;
vector <string> str(s);
for (int i = 0; i < s; i++) {
cin >> str[i];
}
sort(all(str));
map <string, int> mp;
for (int i = 0; i < s; i++) {
mp[str[i]] = i;
}
map <int, string> mp2;
for (int i = 0; i < s; i++) {
mp2[i] = str[i];
}
vector <vector <int>> w(s, vector <int> (s));
for (int i = 0; i < l; i++) {
string ss, tt; cin >> ss >> tt;
w[mp[ss]][mp[tt]] = w[mp[tt]][mp[ss]] = 1;
}
vector <int> a(n);
for (int i = 0; i < n; i++) {
string ss; cin >> ss;
a[i] = mp[ss];
}
vector <int> cnt(s);
for (int i = 0; i < n; i++) {
for (int j = 0; j < s; j++) {
while (cnt[j] < n && (a[cnt[j]] == -1 || w[a[cnt[j]]][j])) {
++cnt[j];
}
if (cnt[j] < n && a[cnt[j]] == j) {
a[cnt[j]] = -1;
cout << mp2[j] << ' ';
break;
}
}
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cout << fixed << setprecision(20);
run();
return 0;
}
還有一種不那么廢腦子的做法,就是我們很容易發現不能交換的物種他們的相對順序不會發生改變。
我們根據這一點進行建圖,若\(i\)位置的物種不能和\(j\)位置的物種交換\((i<j)\),那么連邊\(i\rightarrow j\)。
那么問題就等價於求出一種字典序最小的拓撲序。
但對每個位置\(j\)這樣直接連邊的話空間會炸,可能會到\(O(n^2)\)。這里連邊其實可以優化:對於每個位置,往前面的物種至多連一條邊即可,沒必要多連,這樣就可以保證拓撲序。
細節見代碼:
Code
/*
* Author: heyuhhh
* Created Time: 2020/5/22 11:11:26
*/
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
#define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
void err() { std::cout << std::endl; }
template<typename T, typename...Args>
void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
template <template<typename...> class T, typename t, typename... A>
void err(const T <t> &arg, const A&... args) {
for (auto &v : arg) std::cout << v << ' '; err(args...); }
#else
#define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
struct node {
int u, val;
bool operator < (const node &A) const {
return val > A.val;
}
};
void run() {
int s, l, n;
cin >> s >> l >> n;
vector <string> str(s);
for (int i = 0; i < s; i++) {
cin >> str[i];
}
sort(all(str));
map <string, int> mp;
for (int i = 0; i < s; i++) {
mp[str[i]] = i;
}
map <int, string> mp2;
for (int i = 0; i < s; i++) {
mp2[i] = str[i];
}
vector <vector <int>> w(s, vector <int> (s));
for (int i = 0; i < l; i++) {
string ss, tt; cin >> ss >> tt;
w[mp[ss]][mp[tt]] = w[mp[tt]][mp[ss]] = 1;
}
vector <int> a(n);
for (int i = 0; i < n; i++) {
string ss; cin >> ss;
a[i] = mp[ss];
}
vector <int> in(n), last(s, -1);
vector <vector <int>> edge(n);
for (int i = 0; i < n; i++) {
for (int j = 0; j < s; j++) {
if (last[j] >= 0 && !w[a[last[j]]][a[i]]) {
++in[i];
edge[last[j]].push_back(i);
}
}
last[a[i]] = i;
}
priority_queue <node> q;
for (int i = 0; i < n; i++) {
if (in[i] == 0) {
q.push(node{i, a[i]});
}
}
vector <string> ans;
while (!q.empty()) {
node cur = q.top(); q.pop();
ans.push_back(mp2[cur.val]);
int u = cur.u;
for (auto v : edge[u]) {
if (--in[v] == 0) {
q.push(node{v, a[v]});
}
}
}
for (auto it : ans) cout << it << ' ';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cout << fixed << setprecision(20);
run();
return 0;
}
I. Rats
簽到。
Code
/*
* Author: heyuhhh
* Created Time: 2020/5/21 13:39:18
*/
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
#define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
void err() { std::cout << std::endl; }
template<typename T, typename...Args>
void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
template <template<typename...> class T, typename t, typename... A>
void err(const T <t> &arg, const A&... args) {
for (auto &v : arg) std::cout << v << ' '; err(args...); }
#else
#define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e5 + 5;
void run() {
int n1, n2, n12;
cin >> n1 >> n2 >> n12;
int ans = (n1 + 1) * (n2 + 1) / (n12 + 1) - 1;
cout << ans << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cout << fixed << setprecision(20);
run();
return 0;
}
J. Counting Trees
題意:
現有一顆樹,每個結點上有個標號,並且滿足如下性質,子節點的標號值不小於父親結點。
現在給出這棵樹中序遍歷的標號序列。
問有多少棵樹滿足以上條件。
思路:
顯然這棵樹的根標號值最小,如果所有標號值各不相同,那么很顯然方案數就為\(1\):每次根結點確定,左右子樹遞歸處理。
這給我們提供了一種思路:每次選擇最小的作為根,然后分割過后遞歸進入子樹處理。
出現了個問題,如果有多個值最小怎么辦?那么這些最小的值的深度肯定是盡可能小的,因為我們最開始的根都選擇他們。這些最小值的方案數為卡特蘭數。然后這些最小的數將序列分為幾個部分,每個部分為一個子樹的方案數,當我們最小的數的方案確定時,剩下的其子樹的方案也就確定了(感受一下)。
所以就有一個遞歸做法,序列分割為若干個部分過后遞歸下去,最后把所有結果乘起來即可。
這樣復雜度可能是\(O(n^2)\),代碼量也略大。
這是從小到大,我們可以考慮從大到小,顯然最終一些數在一個連通塊以內,那么他們中間就不可能出現小於的數,否則無論怎樣都會被分割。那么可以根據這一點從大到小枚舉數,然后確定其連通塊,然后可以根據連通塊中他們的個數直接計算答案。最后乘進答案就行。
兩種核心思想都是等價的,只是第二種想法進一步利用了“區間分割”這一性質,我們可以直接對每種數找到其連通塊。
代碼如下:
Code
/*
* Author: heyuhhh
* Created Time: 2020/5/21 15:22:22
*/
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
#define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
void err() { std::cout << std::endl; }
template<typename T, typename...Args>
void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
template <template<typename...> class T, typename t, typename... A>
void err(const T <t> &arg, const A&... args) {
for (auto &v : arg) std::cout << v << ' '; err(args...); }
#else
#define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 2e6 + 5, MOD = 1e9 + 7;
int fac[N], inv[N], INV[N];
int qpow(ll a, ll b) {
ll res = 1;
while (b) {
if (b & 1) res = res * a % MOD;
a = a * a % MOD;
b >>= 1;
}
return res;
}
int C(int n, int m) {
return 1ll * fac[n] * inv[m] % MOD * inv[n - m] % MOD;
}
int cat(int n) {
return 1ll * C(2 * n, n) * INV[n + 1] % MOD;
}
int f[N][21];
int n;
void Get_st(){
for(int j=1;j<=20;j++)
for(int i=1;i<=n;i++)
if(i+(1<<(j-1))<=n) f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
}
int Get_min(int l,int r){
if (l > r) return INF;
int k=0;
while(1<<(k+1)<=r-l+1) k++;
return min(f[l][k],f[r-(1<<k)+1][k]);
}
vector <int> p[N];
void run() {
cin >> n;
fac[0] = 1;
for (int i = 1; i < N; i++) fac[i] = 1ll * fac[i - 1] * i % MOD;
inv[N - 1] = qpow(fac[N - 1], MOD - 2);
for (int i = N - 2; i >= 0; i--) inv[i] = 1ll * inv[i + 1] * (i + 1) % MOD;
for (int i = N - 1; i >= 0; i--) INV[i] = qpow(i, MOD - 2);
memset(f, INF, sizeof(f));
for (int i = 1; i <= n; i++) {
int x; cin >> x;
f[i][0] = x;
p[x].push_back(i);
}
Get_st();
int ans = 1;
for (int i = N - 1; i >= 0; i--) if (sz(p[i])) {
int cnt = 1;
for (int j = 1; j < sz(p[i]); j++) {
int L = p[i][j - 1], R = p[i][j];
if (Get_min(L + 1, R - 1) > i) {
++cnt;
} else {
if (cnt > 1) {
ans = 1ll * ans * cat(cnt) % MOD;
}
cnt = 1;
}
}
if (cnt > 1) {
ans = 1ll * ans * cat(cnt) % MOD;
}
}
cout << ans << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cout << fixed << setprecision(20);
run();
return 0;
}
K. Birdwatching
題意:
給定一顆有根樹,並且給定一個關鍵點\(t\),問有多少點只有一條路徑到達關鍵點\(t\),且這條路徑為\(u\rightarrow t\)。
思路:
暴力的做法:
- 對於每個點刪除\(u\rightarrow t\)這條邊,然后直接\(dfs\)看能不能走到\(t\)。
顯然時間復雜度為\(O(n^2)\),不能承受。
考慮對於所有的點刪除到\(t\)的這條邊,將這樣的點放入集合\(s\)中。顯然如果\(u\in s\),能夠到達\(v\in s\),那么\(u\)就不合法。
注意到這是一個可達性的問題,我們可以考慮建反圖,然后從\(u\in s\)出發進行染色。
若一個點只被自己染色,那么就說明這個點合法。否則被其他點染色就不合法。
這樣考慮復雜度還是沒有變化,我們可以給每個點限制染色個數為\(2\),這樣每個點至多被遍歷兩次,復雜度就降下來變為\(O(n)\)了。
也是一個很巧妙的題。
Code
/*
* Author: heyuhhh
* Created Time: 2020/5/21 18:10:44
*/
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
#define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
void err() { std::cout << std::endl; }
template<typename T, typename...Args>
void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
template <template<typename...> class T, typename t, typename... A>
void err(const T <t> &arg, const A&... args) {
for (auto &v : arg) std::cout << v << ' '; err(args...); }
#else
#define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e5 + 5;
int n, m, t;
vector <int> G[N];
int c1[N], c2[N];
void dfs(int u, int c) {
if (u == t) return;
if (c1[u] == -1) {
c1[u] = c;
} else if(c2[u] == -1) {
if (c1[u] == c) return;
c2[u] = c;
} else return;
for (auto v : G[u]) dfs(v, c);
}
void run() {
cin >> n >> m >> t;
memset(c1, -1, sizeof(c1));
memset(c2, -1, sizeof(c2));
for (int i = 1; i <= m; i++) {
int u, v; cin >> u >> v;
G[v].push_back(u);
}
for (auto it : G[t]) {
dfs(it, it);
}
vector <int> ans;
for (int i = 0; i < n; i++) if (c1[i] == i && c2[i] == -1) {
ans.push_back(i);
}
cout << sz(ans) << '\n';
for (auto it : ans) {
cout << it << '\n';
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cout << fixed << setprecision(20);
run();
return 0;
}
