【luogu P1983 车站分级】 题解

题目链接:https://www.luogu.org/problemnew/show/P1983

符合了NOIP命题的特点,知识点不难,思维量是有的。

step1:把题读进去,理解。得到 非停靠点的等级 < 停靠点的等级

step2:把上述不等关系转化为有向图。即由非停靠点向停靠点连一条边

step3:对于每个入度为零的点dfs找最长路。取其max

step4:输出max+1

code:

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 500010;
int n, m, answer = -1e9, a[1010], start[1010], rudu[1010];
bool flag[1010];
struct edge{
	int next, to, len;
}e[maxn<<2];
int cnt, head[maxn];
int dis[1010];
bool vis[1010], used[1010][1010];
void add(int u, int v, int w)
{
	e[++cnt].to = v; e[cnt].next = head[u]; head[u] = cnt; e[cnt].len = w;
}
int SPFA(int s)
{
	int ans = -1e9;
	queue<int> q;
	while(!q.empty()) q.pop();
	for(int i = 1; i <= n; i++) dis[i] = -1e9;
	memset(vis, 0, sizeof(vis));
	dis[s] = 0, vis[s] = 1, q.push(s);
	while(!q.empty())
	{
		int now = q.front(); q.pop();
		vis[now] = 0;
		for(int i = head[now]; i != -1; i = e[i].next)
		{
			if(dis[e[i].to] < dis[now] + e[i].len)
			{
				dis[e[i].to] = dis[now] + e[i].len;
				if(!vis[e[i].to])
				{
					q.push(e[i].to);
					vis[e[i].to] = 1;
				}
			}
		}
	}
	for(int i = 1; i <= n; i++)
	if(dis[i] != 1e9) ans = max(dis[i], ans);
	return ans;
}

int main()
{
	freopen("testdata.in","r",stdin);
	memset(head, -1, sizeof(head));
	scanf("%d%d",&n,&m);
	for(int i = 1; i <= m; i++)
	{
		int k;
		memset(flag, 0, sizeof(flag));
		memset(a, 0, sizeof(a));
		scanf("%d",&k);
		for(int j = 1; j <= k; j++)
		{
			scanf("%d",&a[j]);
			flag[a[j]] = 1;
		}
		for(int j = a[1]; j <= a[k]; j++)
		{
			if(flag[j] == 0)
			{
				for(int l = 1; l <= k; l++)
				if(used[j][a[l]] == 0)
				{
					add(j, a[l], 1);
					used[j][a[l]] = 1;
					rudu[a[l]]++;
				}
			}
		}
	}//build graph
	int tot = 0;
	for(int i = 1; i <= n; i++)
	if(rudu[i] == 0) start[++tot] = i;
	for(int i = 1; i <= tot; i++)
	answer = max(answer, SPFA(start[i]));
	printf("%d",answer+1);
}

posted @ 2019-06-12 20:37  Misaka_Azusa  阅读(174)  评论(0编辑  收藏
Live2D