题目:车站分级
题意转化:对于一班车,从起点到终点的所有站中,把非经停站向所有经停站连一条长度是1的边,表示前者的等级要严格小于后者的等级
问题:爆空间
解决方法:考虑到这种一群点向另一群点两两连边,可以优化为一群点先向一个虚拟点连一条长度为0边,再从这个虚拟点向另一边连一条长度是1的边,可以把空间从O(N3)优化到O(N2)
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 2010,M=2e6+10;
int h[N], e[M], ne[M], w[M], idx;
void add(int a, int b, int c)
{
e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;
}
int n,m;
int d[N];
int q[N];
int hh,tt=-1;
int dist[N];
bool st[N];
vector<int>tmp;
int main(){
cin>>n>>m;
memset(h, -1, sizeof h);
int vir=1001;
for(int i=1;i<=m;i++){
memset(st, 0, sizeof st);
int tm;
cin>>tm;
int start,end;
for(int j=1;j<=tm;j++){
int c;
cin>>c;
if(j==1)start=c;
if(j==tm)end=c;
st[c]=true;
}
tmp.clear();
for(int i=start;i<=end;i++)
if(!st[i])tmp.push_back(i);
if(tmp.empty())continue;
for(int i=start;i<=end;i++)
if(st[i])add(vir,i,1),d[i]++;
else add(i,vir,0),d[vir]++;
vir++;
}
for(int i=1;i<=n;i++)
if(!d[i])q[++tt]=i,dist[i]=1;
while(hh<=tt){
int t=q[hh++];
for(int i= h[t];~i;i=ne[i]){
int j=e[i];
d[j]--;
if(!d[j])q[++tt]=j;
dist[j]=max(dist[j],dist[t]+w[i]);
}
}
int ma=-1;
for(int i=1;i<=n;i++)ma=max(ma,dist[i]);
cout<<ma<<endl;
}
浙公网安备 33010602011771号