实际上是一道差分约束的题,要求最小值,也就是取所有下界的最大值,用最长路
如果用差分约束spfa的时间复杂度为$O(km)$ ~ $O(nm)$,可能会被卡
因为本题中所有的权值都是正值,因此我们可以不用差分约束就求这个最长路。
我们直接拓扑排序得到一张有向无环图DAG $=>$ 每一个状态都没有循环依赖 $=>$ 没有后效性 $=>$ 就可以用DP递推求最长路。
然后别忘了条件 a >= b + 1 等价于b向a连一条权值为1的边。
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 50007, M = 500007;
int n, m;
int dist[N];//longest way
int ver[M], edge[M], nex[M], head[N], tot;
int q[M];
int din[N];
void add(int x,int y, int z){
ver[tot] = y;
nex[tot] = head[x];
edge[tot] = z;
head[x] = tot ++ ;
din[y] ++ ;
}
bool toposort(){
int hh = 0, tt = -1;
for(int i = 1;i <= n;++i)
if(!din[i]){
q[ ++ tt] = i;
if(tt == M)tt = 0;//round-robin queue
}
while(hh <= tt){
int x = q[hh ++ ];
if(hh == M)hh = 0;
for(int i = head[x];~i;i = nex[i]){
int y = ver[i];
if(-- din[y] == 0)
q[++ tt] = y;
}
}
return tt == n - 1;//because the initial tt which had been used is 0;
}
int main(){
scanf("%d%d",&n,&m);
memset(head,-1,sizeof head);
for(int i = 1; i <= m;++i){
int x,y;
scanf("%d%d", &x, &y);
add(y,x,1);//a >= b + 1 -> (b,a,1)
}
if(!toposort())puts("Poor Xed");
else {
for(int i = 1;i <= n;++i)dist[i] = 100;
for(int i = 0;i < n;++i){//run the topological sequence
//be attention to the array q is beginning in 0
int x = q[i];
for(int j = head[x];~j;j = nex[j]){
int y = ver[j], z = edge[j];
dist[y] = max(dist[y], dist[x] + z);
}
}
int res = 0;
for(int i = 1;i <= n;++i)
res += dist[i];
printf("%d\n",res);
}
return 0;
}