http://acm.ecnu.edu.cn/problem/3464/
给定一个n个点m条边的图,要求删掉一些边使得图仍然强连通且只剩2n条边。问删去哪些边。
我觉得这就是一题Kosaraju模板题。。随便选个点dfs,然后反向建图再让所有点往刚才选的这个点dfs,这样经过的边就是必须留下的边了。尽管没有tarjan那么简单,但实际上还是不难理解的。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
struct node
{
int to, index;
};
int u[maxn], v[maxn];
vector<node> g1[maxn], g2[maxn];
bool cut[maxn], vis[maxn];
void dfs(int now, vector<node>* g)
{
vis[now] = true;
for (auto &i: g[now])
{
if(vis[i.to]) continue;
cut[i.index] = true;
dfs(i.to, g);
}
}
int main()
{
int t, n, m;
cin >> t;
while (t--)
{
memset(cut, false, sizeof cut);
memset(vis, false, sizeof vis);
scanf("%d%d", &n, &m);
for (int i = 0; i <= n; ++i)
{
g1[i].clear();
g2[i].clear();
}
node p;
for (int i = 1; i <= m; ++i)
{
scanf("%d%d", u+i, v+i);
p.to = v[i];
p.index = i;
g1[u[i]].push_back(p);
p.to = u[i];
p.index = i;
g2[v[i]].push_back(p);
}
dfs(1, g1);
memset(vis, false, sizeof vis);
dfs(1, g2);
int cnt = m-2*n;
for (int i = 1; i <= m && cnt; ++i)
if (!cut[i])
{
--cnt;
printf("%d %d\n", u[i], v[i]);
}
}
return 0;
}