2019-2020 ICPC Southwestern European Regional Programming Contest (SWERC 2019-20)
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;
}
重要的是自信,一旦有了自信,人就会赢得一切。