洛谷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
题解
这是样例的图
再看一下输入的描述,你会发现所有路径都是从编号小的到编号大的。既然这样,那编号大的肯定能由编号小的推出来。
这其实就是核心的思路了。具体流程看注释吧
#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
", tmp);
printf("%d
", f[tmp]);
return 0;
}