[dp]Link with Level Editor I 2022牛客多校第2场 L

题目描述 

Please pay attention to the unusual memory limit.

Link is playing a game, called NIO's Game.

In this game, a level consists of several worlds. Each world consists of mmm nodes and some directed roads. The player starts on node 111 of the first world. In each world, the player can either stay at current node or go through exactly one road that exists in that world. After that, the player will be teleported to the next world without changing the ID of the node where he stays. If there is no next world, the game ends. The player wins if he ends on node mmm.

Link is editing a new level, he has already made nnn worlds (numbered from 111 to nnn) and wants to choose a continuous subsegment of them to form a new level. The only limit is that there should be at least one way to win.

Link doesn't want to use too many worlds. What is the minimum number of worlds Link needs to use in the new level?

输入描述:

The first line contains two integers n,mn,mn,m (1≤n≤104,2≤m≤2×1031 \leq n \leq 10^4, 2 \leq m \leq 2 \times 10^31≤n≤104,2≤m≤2×103).

The following input describes the worlds numbered from 111 to nnn. For each world:

The first line contains an integer lll (0≤l≤m×(m−1)0 \leq l \leq m \times (m-1)0≤l≤m×(m−1)), which is the number of roads in this world.

In the next lll lines, each line contains two integers u,vu,vu,v (1≤u,v≤m,u≠v1 \leq u,v \leq m, u \neq v1≤u,v≤m,u​=v), which means there is a road from node uuu to node vvv in this world.

For each world, it is guaranteed that there is no duplicate edge.

For each test point, it is guaranteed that the sum of lll does not exceed 10610^6106.

输出描述:

Output a single integer, which is the minimum number of worlds Link needs to use in the new level. If Link couldn't make such a level, output −1-1−1.

示例1

输入

3 3
1
2 1
1
2 3
1
1 2

输出

-1

示例2

输入

3 3
1
2 1
1
1 2
1
2 3

输出

2

题意: 有n个世界,每个世界中都包含m个点,不同世界的图是不同的,现在要从点1走到点m,在某个世界中可以做两种操作,要么呆在原地不动,要么通过一条边走向其他点,在这之后就会被传送至下一个世界,问从1到m需要经过的最少世界数。

分析: 一开始感觉是分层图的裸题,但用分层图的话空间会被卡住,正解是dp,设dp[i][j]为在第i个世界到达j点时最晚从哪个世界出发,设对状态后状态转移就很明显了,在某个世界时无非就两种操作,要么不动要么走一步,当选择不动时dp[i][j] = max(dp[i][j],dp[i-1][j]),当选择走一步时dp[i][j] = max(dp[i][j],dp[i-1][to]),其中to是所有能在i-1世界中走到j的点,这部分更新需要枚举第i-1世界中所有边,最终复杂度为O(n*m),不过需要注意的是dp数组要开到2e7,而这题严格卡了空间,所以必须滚动数组优化空间,最后答案就是max(i-dp[i][m]),i∈[2, n+1]。

具体代码如下:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#define inf 0x3f3f3f3f
using namespace std;

int dp[2][2005];//dp[i][j]表示在第i个世界中走到j点最晚出发的世界 
vector<int> g[2005];
signed main()
{
	int n, m;
	scanf("%d%d", &n, &m);
	int num;
	scanf("%d", &num);
	for(int j = 1; j <= num; j++){
		int u, v;
		scanf("%d%d", &u, &v);
		g[v].push_back(u);//建反向边 
	}
	int ans = inf;
	dp[1][1] = 1;
	for(int i = 2; i <= n+1; i++){
		dp[i%2][1] = i;
		for(int j = 2; j <= m; j++){
			dp[i%2][j] = dp[(i-1)%2][j];
			for(int k = 0; k < g[j].size(); k++){
				int to = g[j][k];
				dp[i%2][j] = max(dp[i%2][j], dp[(i-1)%2][to]);
			}
		}
		if(dp[i%2][m] != 0) ans = min(ans, i-dp[i%2][m]);
		if(i == n+1) break;
		for(int j = 1; j <= m; j++) g[j].clear();
		scanf("%d", &num);
		for(int j = 1; j <= num; j++){
			int u, v;
			scanf("%d%d", &u, &v);
			g[v].push_back(u);
		} 
	}
	if(ans != inf) printf("%d\n", ans);
	else puts("-1");
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值