[省选联考 2021 A/B 卷] 图函数
考虑到一件事情首先\(u -> u\)是可行的。
所以其实对于\(f(u,G')\) 只要考虑\([1,u]\)的点。
那么考虑其条件等价于\(u -> i\) 和 \(i -> u\) 都不经过\([1,u)\)的点。
不然我们显然可以构造出一种情况,使得在路径上某个点被删掉。
那么考虑我们对全局进行一个答案的求。
考虑我们设\(g(x,y)\) 满足给定条件。
那么接着考虑我们的这个边的条件。
我们只要求出这个\(i -> j\)限定只能经过\([k + 1,n]\)这些点的最小值的最大值即可。
直接folyd,O(n^3).
考虑加入一波优化。
我们在限制\(i > lim\)时只更新小于\(lim\)的量即可少一半常数。
#include<iostream>
#include<cstdio>
#include<vector>
#define ll long long
#define N 1005
#define M 200005
int n,m;
int f[N][N];
int ans[M];
int g[M];
int main(){
// freopen("graph.in","r",stdin);
// freopen("graph.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i = 1;i <= m;++i){
int u,v;
scanf("%d%d",&u,&v);
f[u][v] = i;
}
for(int lim = n;lim >= 1;--lim){//点的限制
for(int i = n;i >= lim + 1;--i)
// for(int i = 1;i < lim;++i)
g[std::min(f[lim][i],f[i][lim])] ++ ;
for(int i = 1;i <= n;++i){
if(!f[i][lim])continue;
if(i > lim)
for(int j = 1;j < lim;++j)
f[i][j] = std::max(f[i][j],std::min(f[i][lim],f[lim][j]));
else
for(int j = 1;j <= n;++j)
f[i][j] = std::max(f[i][j],std::min(f[i][lim],f[lim][j]));
}
}
ans[m + 1] = n;
for(int i = m;i >= 1;i--)
ans[i] = ans[i + 1] + g[i];
for(int i = 1;i <= m + 1;++i)
std::cout<<ans[i]<<" ";
}