题意描述:

给一个N个点,M条边的有向图,和起点R,定义一条边为多余边,满足:起点R能够不经过该边到达所有N个点。

问哪些边是多余的,输出多余边的条数,并按顺序输出所有多余的边

1 <= N <= 100000 , 1 <= M <= 200000

输入:

4 6 2
2 1
2 3
3 1
3 4
1 4
4 2

输出:

5
1 3 4 5 6


解题思路:

将边变成点,如果某条边的点是某个点的支配点,那么这条边不能被删除,既这条边不是多余的边。

剩下的边就都是多余的边了。支配树模板搞一搞。

Redundant Edges(支配树)_有向图

代码:

#include<bits/stdc++.h>
using namespace std;

/*********支配树模板**********/
//init(N) -> link(u,v) -> work(root) -> idom[i]:root到距离i最近的必经点
const int N = 300010, M = 400010;
struct eg{ int v, next; }e[M]; //link times
int tim, tot, h[N], iw[N], li[N], fa[N], fo[N], vo[N], sdom[N], idom[N];
vector<int> pre[N], bkt[N];
inline void link(int u, int v){
e[++tot].v = v, e[tot].next = h[u], h[u] = tot;
pre[v].push_back(u);
}
void dfs(int p){
sdom[p] = iw[p] = ++tim, li[tim] = p;
for (int i = h[p]; i; i = e[i].next)
if (!iw[e[i].v]) dfs(e[i].v), fa[e[i].v] = p;
}
int findf(int p){
if (fo[p] == p) return p;
int r = findf(fo[p]);
if (sdom[vo[fo[p]]] < sdom[vo[p]]) vo[p] = vo[fo[p]];
return fo[p] = r;
}
inline int eval(int p){ findf(p); return vo[p]; }
inline void work(int root){
int p, fp; dfs(root);
for (int i = tim; i >= 2; i--){
p = li[i];
for (int &k : pre[p])
if (iw[k]) sdom[p] = min(sdom[p], sdom[eval(k)]);
bkt[li[sdom[p]]].push_back(p);
fp = fo[p] = fa[p];
for (int v : bkt[fp]){
int u = eval(v);
idom[v] = sdom[u] == sdom[v] ? fp : u;
}
bkt[fp].clear();
}
for (int i = 2; i <= tim; i++)
p = li[i], idom[p] = idom[p] == li[sdom[p]] ? idom[p] : idom[idom[p]];
for (int i = 2; i <= tim; i++)
p = li[i], sdom[p] = li[sdom[p]];
}
void init(int n){
tim = tot = 0;i
for (int i = 1; i <= n; i++)
h[i] = iw[i] = 0, fo[i] = vo[i] = i, pre[i].clear(), bkt[i].clear();
}
/*******************/

int n, m, rt, a, b;
bool vis[M];
set<int> s;
int main(){
scanf("%d %d %d", &n, &m, &rt);
init(n + m);
for (int i = 1; i <= m; i++)
scanf("%d %d", &a, &b), link(a, i + n), link(i + n, b);
work(rt);
for (int i = 1; i <= n; i++) if (idom[i] > n) vis[idom[i] - n] = 1;
for (int i = 1; i <= m; i++) if (!vis[i]) s.insert(i);
printf("%d\n", s.size());
for (auto &k : s) printf("%d%c", k, k == *s.rbegin() ? '\n' : ' ');
return 0;
}