洛谷P2196 挖地雷

洛谷P2196 挖地雷

题目链接 https://www.luogu.com.cn/problem/P2196

题目大意

给你n个地窖和路径,求最多能挖多少雷,和挖雷最多的路径。

输入

第一行一个整数n表示有n个地窖

第二行有n个整数表示每个地窖的地雷数

以下有若干行,每行有两个数x,y表示x可以到y,保证x小于y

最后一行有两个0,表示输入结束

输出

第一行输出挖地雷的顺序。

第二行为最多挖出的地雷数

样例

输入 #1

5
10 8 4 7 6
1 1 1 0
0 0 0
1 1
1

输出 #1

1 3 4 5
27

题解

1587780725847

这是样例的图

再看一下输入的描述,你会发现所有路径都是从编号小的到编号大的。既然这样,那编号大的肯定能由编号小的推出来。

这其实就是核心的思路了。具体流程看注释吧

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn = 1e3;
int n, x, y, ans, cnt, a[maxn], g[maxn][maxn], pre[maxn], pos, f[maxn], que[maxn];//f[i]表示前i号节点的最大数量
int main(){
	scanf("%d", &n);
	for(int i=1; i<=n; i++) scanf("%d", &a[i]);
	while(scanf("%d%d", &x, &y)){
		if(x == 0 && y == 0) break;
		g[x][y] = 1;//记录路径
	}
	for(int i=1; i<=n; i++){//路径的终点
		for(int j=1; j<=i; j++)//路径的起点,编号一定小于终点
			if(g[j][i] && f[j]>f[i])//如果是联通的,且方案更优
				f[i] = f[j], pre[i] = j;//更新一下f[i],并且记录i是从j点走过来的
		f[i] += a[i];//把当前点挖了
		if(f[i] > ans)
			ans = f[i], pos = i;//更新ans,和整条路径的终点pos
	}
	int tmp = pos;
	while(pre[pos]){//把路径存到que里
		que[++cnt] = pre[pos];
		pos = pre[pos];
	}
	for(int i=cnt; i>=1; i--) printf("%d-", que[i]);
	printf("%d\n", tmp);
	printf("%d\n", f[tmp]);
	return 0;
}  
posted @ 2020-04-25 10:27  poozhai  阅读(123)  评论(0编辑  收藏  举报