题目链接:https://icpc-camp-cdn.b0.upaiyun.com/permanent/problems/sichuan-2017.pdf
题意简述:给你一个有向无环图,可以把图上的点涂成白色或黑色(初始都是白点),问起点到终点存在路径都是白点的点对有多少个?
分析:首先点数只有300,预计复杂度为O(N^2*q),DFS加bitset优化可以过就不讲了。
官方题解是这样说的:
可以 O(n^2) 维护 f(x, y) 表示从 x, y 的路径条数。例如删掉点 v,就是 f(x, y) 减去 f(x, v) × f(v, y).之后就可以通过 f(x, y) > 0 来判断 x 到 y 是否可达了。
但有几点需要注意,
- 需要O(n^3)构造出路径条数的矩阵,代码如下。
for(int k=1; k<=n; ++k)
for(int i=1; i<=n; ++i)
for(int j=1; j<=n; ++j)
a[i][j] += a[i][k]*a[k][j];
- 删点比较简单,但还原点有些难度,首先边的信息不能丢了,然后还原出f(v,y)和f(x,v),接着再还原f(x,y)
代码如下
void del(int u) {
for(int i=1; i<=n; ++i)
for(int j=1; j<=n; ++j)
a[i][j] -= a[i][u]*a[u][j];
for(int i=1; i<=n; ++i)
a[i][u] = a[u][i] = 0;
}
void add(int u) {
for(int i=1; i<=n; ++i)
for(int j=1; j<=n; ++j)
if(color[i]==White&&color[j]==White) {
a[u][i] += e[u][j]*a[j][i];
a[i][u] += a[i][j]*e[j][u];
}
for(int i=1; i<=n; ++i)
if(color[i]==White) {
a[u][i] += e[u][i];
a[i][u] += e[i][u];
}
for(int i=1; i<=n; ++i)
for(int j=1; j<=n; ++j)
if(color[i]==White&&color[j]==White)
a[i][j] += a[i][u]*a[u][j];
}