对每趟车建一个虚点p,对于不停车的x,连边(x,p,1);对于停车的y,连边(p,y,0)
有一条边(a,b,l)就是说b-a>=l
由于题目保证一定能走,直接拓扑序dp算最大的就行了
#include<bits/stdc++.h> #define pa pair<int,int> #define CLR(a,x) memset(a,x,sizeof(a)) using namespace std; typedef long long ll; const int maxn=2e3+10,maxm=2e6+10; inline ll rd(){ ll x=0;char c=getchar();int neg=1; while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();} while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); return x*neg; } struct Edge{ int b,l,ne; }eg[maxm]; int egh[maxn],ect,N,M,f[maxn],ine[maxn]; queue<int> q; inline void adeg(int a,int b,int c){ eg[++ect].b=b,eg[ect].l=c,eg[ect].ne=egh[a],egh[a]=ect; ine[b]++; } int main(){ //freopen("","r",stdin); int i,j,k; N=rd(),M=rd(); for(i=1;i<=M;i++){ int p=N+i; j=rd()-1,k=rd(); adeg(p,k++,0); for(;j;j--){ int x=rd(); for(;k<x;k++) adeg(k,p,1); adeg(p,k++,0); } } for(i=1;i<=N+M;i++) if(!ine[i]) q.push(i); int ans=0; while(!q.empty()){ int p=q.front();q.pop(); for(i=egh[p];i;i=eg[i].ne){ int b=eg[i].b;ine[b]--; f[b]=max(f[b],f[p]+eg[i].l); ans=max(ans,f[b]); if(!ine[b]) q.push(b); } } printf("%d ",ans+1); return 0; }