AcWing 456. 车站分级

原题链接AcWing 456. 车站分级

抽象出题意,停靠过的车站的等级一定严格大于为停靠过的车站的等级,且不存在环,例如车站A等级大于车站B,则A>=B+1,不妨从BA连一条边,表示等级关系,题目要求车站的最小等级中最大是多少,即求最长路,那这就是一个差分约束系统。

而对于差分约束系统:
如果边权有正有负:则使用spfa
如果边权非负,那么可以使用tarjan缩点+递推,+的方式求最长路或者最短路。

同时,对于本题,把未停靠的站点和停靠的分成两个集合,那么需要连边最坏情况下是要n2,考虑最坏情况下,一共有1000趟车,每一趟都是从1~n站,其中停靠了500个站,还有500个未停靠,那么这时候连边就是5005001000=250000000,显然,复杂度爆炸,但是考虑一种优化,在集合中间建立虚拟结点,左边边权是0,右边边权是1,那么就优化成了O(n+m)连边方式了,再算一下最坏情况下的数据量,(500+500)1000=1000000,这样就可以过了,直接优化成了线性,并且完全等价于O(n2)连边的方式。
image

// Problem: 车站分级
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/458/
// Memory Limit: 64 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>

using namespace std;

const int N = 2010, M = 1E6 + 10;

int h[N], e[M], ne[M], w[M], idx;
int n, m;
int d[N];
int dist[N];
int seq[N], cnt;
bool st[N];

void add(int a, int b, int c) {
	e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
	d[b]++;
}

void topsort() {
	queue<int> q;
	for (int i = 1; i <= n + m; i++) {
		if (!d[i]) q.push(i);
	}
	
	while (q.size()) {
		int t = q.front();
		q.pop();	
		
		seq[cnt++] = t;
		
		for (int i = h[t]; ~i; i = ne[i]) {
			int j = e[i];
			if (--d[j] == 0) q.push(j);
		}
	}
}

int main() {
	scanf("%d%d", &n, &m);
	memset(h, -1, sizeof h);
	for (int i = 1; i <= m; i++) {
		int cnt;
		scanf("%d",  &cnt);
		memset(st, 0, sizeof st);
		int start = n, end = 1;
		while (cnt--) {
			int k;
			scanf("%d", &k);
			start = min(start, k);
			end = max(end, k);
			st[k] = true;
		}	
		
		int vir = n + i;
		for (int j = start; j <= end; j++) {
			if (!st[j]) add(j, vir, 0);
			else add(vir, j, 1);
		}
	}
	
	topsort();
		
	for (int j = 1; j <= n; j++) dist[j] = 1;
	for (int j = 0; j < n + m; j++) {
		int var = seq[j];
		for (int k = h[var]; ~k; k = ne[k]) {
			dist[e[k]] = max(dist[e[k]], dist[var] + w[k]);
		}
	}
	
	int res = 0;
	for (int i = 1; i <= n; i++) res = max(res, dist[i]);
	printf("%d\n", res);
	
    return 0;
}
posted @   Xxaj5  阅读(108)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
历史上的今天:
2020-08-24 P1126 机器人搬重物
点击右上角即可分享
微信分享提示