题目大意
没有环的有向图称为有向无环图,这是一个多么美好的结构吖。
如果有一张有 N N N 个点的有向图,我们可能需要删掉一些边使它变成一张有向无环图。假设初始时我们只有 N N N 个互不相连的点,当然它也是一张有向无环图。依次给出 T T T 条边和每条边的方向。 每给出一条边就要立即决定是否要加入这一条边,使得这张图始终是一张有向无环图(意思是:按顺序处理每条边,能加就加,让你模拟这个过程,自环不能加入)。计算在满足要求的情况下一共有多少条边没有被加入。如果所有边都可以加入这张图则输出 0 0 0。
注意有向无环图是可以存在重边的。即:若原图有边 1 → 2 1 \to 2 1→2,则新边 1 → 2 1 \to 2 1→2 可被加入。
对于 100 % 100\% 100% 的数据, n < = 250 n<=250 n<=250, T < = 100000 T<=100000 T<=100000。
解题思路
用一个数组 Map
记录
u
u
u 是否可以到达
v
v
v。
对于一组输入的边 u → v u \to v u→v,其需要经历一下流程:
- 如果 v v v 可达 u u u,说明如果建了 u → v u \to v u→v,就形成了一个环,答案加 1 1 1。
- 如果已经有一条边 u → v u \to v u→v 了,那么当前输入的这条边不再需要执行任何操作,直接跳过。
- 用两个临时数组 a a a 和 b b b 记录有哪些点可达点 u u u,以及点 v v v 可达哪些点。
- 双重循环遍历两个数组,将 M a p [ a i ] [ b j ] Map[a_i][b_j] Map[ai][bj] 标记为 1 1 1,因为将边 u → v u \to v u→v 加上后,这些点都可以到达。
其实这道题用记忆化搜索也可以。
就是对于一组输入的边
u
→
v
u \to v
u→v,dfs
一下,判断
v
v
v 是否可达
u
u
u:
- 若可以到达,则不加上这条边。
- 若不能到达,则加上这条边。
dfs
的话用数组记录答案就行了,避免重复地 dfs
。
其实这题还可以改改, m a n g o 13 mango13 mango13 曰:可以将本题改成强制离线(这题是在线判断的)的。
以下目前我的思路,期待被 HACK
:
先用有向图 Tarjan
判环,然后循环一下所有的边,记录强连通分量里有多少条边。
则将强连通分量拆成有向无环图,就需要拆 m − n + 1 m-n+1 m−n+1 条边( m m m 是强连通分量里的边的数量, n n n 是强连通分量里的点的数量)。
正在创数据中~~~
等待更新~~~
AC CODE
#include <bits/stdc++.h>
using namespace std;
int Map[251][251];
int a[251], b[251];
int al, bl, ans;
int n, m, u, v;
signed main()
{
cin >> n >> m;
for (int i = 1; i <= n; ++i)
Map[i][i] = 1;
while (m--)
{
cin >> u >> v;
if (Map[v][u])
{
++ans;
continue;
}
if (Map[u][v])
continue;
al = bl = 0;
for (int i = 1; i <= n; ++i)
if (Map[i][u])
a[++al] = i;
for (int i = 1; i <= n; ++i)
if (Map[v][i])
b[++bl] = i;
for (int i = 1; i <= al; ++i)
for (int j = 1; j <= bl; ++j)
Map[a[i]][b[j]] = 1;
}
cout << ans;
return 0;
}