对于无向边在建图时:
正向a->b:边权为2
反向b->a:边权为3
- 最大化s的连通点数,dfs(s), 搜到w[i]=2时,记录正向边(后续为+), 没有记录到的为-
- 最小化s的连通点数,dfs(s), 搜到w[i]=2时,记录此边为反向边(后续为-),没有记录到的为+
参考了:https://www.acwing.com/activity/content/code/content/7394314/
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include "bits/stdc++.h"
using namespace std;
#define ios ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define fios ofstream out("test.txt");cout.rdbuf(out.rdbuf())
#define endl "\n"
#define lowbit(x) (x & (-x))
#define INF 0x3f3f3f3f
#define MINF 2147483647
#define eps 1e-6
#define PI acos(-1)
typedef long long LL;
typedef pair<int, int> PII;
#define x first
#define y second
const int N = 300010, M = N * 2;
int n, m, s;
int h[N], e[M], w[M], ne[M], idx;
vector<PII> edge;
bool st[N];
bool st1[N], st2[N];
set<PII> s1, s2;
void add(int a, int b, int c)
{
e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
}
void dfs1(int u)
{
st1[u] = true;
for(int i = h[u]; i != -1; i = ne[i])
{
int j = e[i];
if(st1[j]) continue;
if(w[i] == 2) s1.insert({u, j});
//else if(w[i] == 3) s.insert({j, u});
dfs1(j);
}
}
void dfs2(int u)
{
st2[u] = true;
for(int i = h[u]; i != -1; i = ne[i])
{
int j = e[i];
if(st2[j]) continue;
if(w[i] == 1) dfs2(j);
else if(w[i] == 2) s2.insert({u, j});
}
}
int main()
{
cin >> n >> m >> s;
memset(h, -1, sizeof h);
for(int i = 0; i < m; i++)
{
int t, a, b;
cin >> t >> a >> b;
if(t == 1) add(a, b, 1);
else
{
edge.push_back({a, b});
add(a, b, 2), add(b, a, 3); // 2 +, 3 -
}
}
dfs1(s);
int cnt = 0;
string res = "";
for(int i = 1; i <= n; i++)
if(st1[i]) cnt++;
for(auto e : edge)
{
if(s1.count({e.x, e.y})) res += '+';
else res += '-';
}
cout << cnt << endl;
cout << res << endl;
cnt = 0;
res = "";
dfs2(s);
for(int i = 1; i <= n; i++)
if(st2[i]) cnt++;
for(auto e : edge)
{
if(s2.count({e.x, e.y})) res += '-';
else res += '+';
}
cout << cnt << endl;
cout << res << endl;
return 0;
}