Hzy's Rabbit Candy
题目描述
Hzy和她的m只兔兔在一个n个点m条边的有向无环图上玩。
为了让兔兔们开心,Hzy带了一些糖。Hzy可以从任何一个点开始,走到任何一个点结束。在这途中,每当Hzy经过一个点i,她会捡到ai块糖;每当Hzy经过一条边j,这条边上的兔兔会吃掉她的bj块糖。
Hzy希望能在结束时保留尽量少的糖,请求出Hzy在结束时的糖的数量相对于开始时的糖的数量最多减少多少(请注意,Hzy的糖可能无论如何都无法减少,此时答案是一个非正整数)。
输入
第一行两个正整数n、m(1≤n≤100000,1≤m≤500000),表示点数和边数。
之后的一行n个正整数以空格隔开,第i个正整数ai表示经过第i个点Hzy会捡到的糖的数量。
之后的m行,每行三个正整数uj,vj,bj,表示一条从uj到vj的边,Hzy经过这条边时,兔兔会吃掉bj块糖。
输出
一行一个正整数,表示Hzy在结束时的糖的数量相对于开始时的糖的数量最多减少多少。
样例输入
复制样例数据
3 5
1 2 3
1 2 10
1 2 11
2 3 10
2 3 11
1 3 15
样例输出
16
【题意】:
可以 以任何点为起点,和终点。然后到达该点会获得a[i],然后经过这条边就会减少相应的边的权值。
然后问,请问怎样才能减少的最多。
【题解】:
首先我们应该反着想,你不说减少最多吗?而且求最大的减少量,那么这个其实可以反着题目。
题目说到达某点时会增加,你看作减少,经过某边减少权值,你可以看作增加。
然后进行拓扑排序,然后在过程中更新dp[ ] 来实现。
具体可以看代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e5+10;
typedef struct Edge{
int to,next,w;
Edge(int to=0,int next=0,int w=0):to(to),next(next),w(w){}
}Edge;
Edge e[N];
int head[N],cnt=0;
void add_edge(int u,int v,int w){
e[cnt]=Edge(v,head[u],w);
head[u]=cnt++;
}
ll dp[N];
int a[N];
int du[N];
int main()
{
memset(head,-1,sizeof(head));
int n,m;
ll ans=-N;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
a[i]=-a[i];
dp[i]=a[i];
ans=max(ans,dp[i]);
}
for(int i=0;i<m;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add_edge(u,v,w);
du[v]++;
}
queue<int>q;
for(int i=1;i<=n;i++){
if(!du[i]){
q.push(i);
}
}
while(!q.empty()){
int u=q.front();
q.pop();
for(int i=head[u];~i;i=e[i].next){
int to=e[i].to;
ll tmp=dp[u]+e[i].w+a[to];
dp[to]=max(dp[to],tmp);
ans=max(ans,dp[to]);
du[to]--;
if(du[to]==0){
q.push(to);
}
}
}
printf("%lld\n",ans);
return 0;
}