挖地雷
和洛谷题不完全相同,千万别抄
这道题用记忆化搜索,虽然拓扑排序也行但是我不会
状态转移方程:dp[i]=max(dp[i],dp[j])
dp[j]表示从j出发,能挖到的最多地雷数,然后每个点枚举一下就ok了
AC代码:
#include<bits/stdc++.h>
using namespace std;
int n,a[2005],ans,dp[2005];
struct edge
{
int to,nxt;
}e[20005];
int head[2005],ecnt,next[2005];
void add(int x,int y)
{
e[++ecnt].nxt=head[x];
e[ecnt].to=y;
head[x]=ecnt;
}
int dfs(int x)
{
if(dp[x]) return dp[x];//搜到过就返回dp[x]
dp[x]=a[x];//dp[x]=当前点权
for(int i=head[x];i;i=e[i].nxt)
{
int t=dfs(e[i].to);//记忆化往后搜
if(dp[x]<t+a[x])
{
dp[x]=t+a[x];
next[x]=e[i].to;//记录路径
}
}
return dp[x];
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
int u,v;
while(1)//建边
{
cin>>u>>v;
if(u==0&&v==0) break;
add(u,v);
}
int st;
for(int i=1;i<=n;i++)
{
if(ans<dfs(i))
{
ans=dfs(i);
st=i;
}
}
while(st)//递归输出路径
{
cout<<st;
st=next[st];
if(st) cout<<"-";
}
cout<<endl;
printf("%d",ans);
return 0;
}
/*
6
5 10 20 5 4 5
1 2
1 4
2 4
3 4
4 5
4 6
5 6
0 0
*/