题意:
图中有有向边和无向边,可能有重边。现要把原图中的无向边全变成有向边,构造两个图:第一个图最大化从s点出发能到达的点数,第二个图最小化从s点出发能到达的点数
思路:
dfs,遇到有向边就直接走,遇到无向边时:
若要取max就把边的方向置为 u->v,并继续走;
若要取min就把边的方向置为 v<-u,注意接下来不能走到v。
const int N = 3e5 + 5;
int n, m, s;
vector<PII> G[N]; //to,id(id=0有向边,>0无向边)
int vis[N], start[N], ans, opp[N], idx;
//idx无向边数,opp某条边是否要反向,start某无向边原来的起点
bool ismin;
void dfs(int u)
{
ans++, vis[u] = 1;
for(auto [v, id] : G[u])
{
if(vis[v]) continue;
if(!id) dfs(v); //有向边,继续走
else if(ismin) opp[id] = (start[id] != v); //无向边,看要不要反向
else opp[id] = (start[id] != u), dfs(v);
}
}
signed main()
{
iofast;
cin >> n >> m >> s;
for(int i = 1; i <= m; i++)
{
int t, u, v; cin >> t >> u >> v;
if(t == 1) G[u].pb({v,0});
else start[++idx] = u, G[u].pb({v,idx}), G[v].pb({u,idx});
}
dfs(s);
//输出答案
cout << ans << endl;
for(int i = 1; i <= idx; i++) cout << (opp[i]?'-':'+');
cout << endl;
//init
memset(opp, 0, sizeof opp);
memset(vis, 0, sizeof vis);
ans = 0, ismin = 1;
dfs(s);
//输出答案
cout << ans << endl;
for(int i = 1; i <= idx; i++) cout << (opp[i]?'-':'+');
}