题目
题解思路
建立有向边来表示差分约束。
会大一级就建1边 。站点之间不建边。使得答案最小。(贪心)
这样图的最长路就是答案了。
而拓扑序利用边权来更新最大值,就可以满足答案是最长路(根据拓扑排序的定义理解)。
再这样再跑一遍拓扑序来得出答案。
这样车站之间建边可能会变成nn , y总用虚拟点优化使得只需2n条边即可。
AC代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <algorithm>
#include <map>
#include <string>
using namespace std;
const int INF = 0x3f3f3f3f;
struct node
{
int q , w ;
};
vector <node> head[2010] ;
int a[2010] ;
int vis[2010] ;
int main ()
{
ios::sync_with_stdio(false);cin.tie(0);
int n , m ;
cin >> n >> m ;
int cnt = n + 1 ;
for ( int i = 1 ; i <= m ; i++ )
{
int t ;
cin >> t ;
int fx = 1 ;
vector <int> mi ;
vector <int> mx ;
for (int j = 1 ; j <= t ; j++ )
{
int t1 ;
cin >> t1 ;
mx.push_back(t1) ;
if ( j == 1 )
{
fx = t1 ;
continue ;
}
if ( t1 > fx )
{
fx ++ ;
while ( fx < t1 )
{
mi.push_back(fx);
// cout << fx << "\n" ;
fx ++ ;
}
}
}
if ( mi.size() )
{
for ( auto j : mi )
{
head[j].push_back({cnt,0}) ;
a[cnt]++;
//cout << j << " " << cnt << "\n" ;
}
for ( auto k : mx )
{
head[cnt].push_back({k,1}) ;
a[k]++;
}
cnt++ ;
}
}
queue <int> q ;
for ( int i = 1 ; i < cnt ; i++ )
{
vis[i] = 1 ;
if ( a[i] == 0 )
{
vis[i] = 1 ;
q.push(i) ;
}
}
vector <int> ts ;
while ( !q.empty() )
{
int tmp = q.front() ;
ts.push_back(tmp) ;
q.pop() ;
for ( int i = 0 ; i < head[tmp].size() ; i++ )
{
int p = head[tmp][i].q ;
a[p] -- ;
if ( a[p] == 0 )
{
q.push(p) ;
}
}
}
int ans = 1 ;
for ( int i = 0 ; i < ts.size() ; i++ )
{
for ( int j = 0 ; j < head[ts[i]].size() ; j++ )
{
vis[ head[ts[i]][j].q ] = max( vis[ head[ts[i]][j].q ] , vis[ts[i]] + head[ts[i]][j].w ) ;
// ans = max( vis[ head[i][j].q ] , ans );
}
}
for ( int i = 1 ; i <= n ; i++ )
ans = max( ans , vis[i] ) ;
cout << ans << "\n" ;
return 0 ;
}