一开始想着最短路时统计一下到每个点的牛数量,但是没写出来
建最短路树是个不错的想法,正常跑一次最短路,枚举每个点的前驱,如果d[y]==d[x]+w就是树上的一条边,优先连编号小的,
建好树以后做一次dfs,枚举一下每个点的贡献取个最大值即可
#include<bits/stdc++.h> #define mp make_pair #define ll long long using namespace std; const int maxn=10010; const int maxm=50010; int n,m,t;ll ans; priority_queue<pair<ll,int> >q; struct node{ int v,w,nxt; }e[maxm*2],e2[maxm*2]; ll d[maxn],c[maxn],w[maxn]; bool v[maxn]; int head[maxn],cnt; void add(int u,int v,int w){e[++cnt].v=v;e[cnt].w=w;e[cnt].nxt=head[u];head[u]=cnt;} int head2[maxn],cnt2; void add2(int u,int v,int w){e2[++cnt2].v=v;e2[cnt2].w=w;e2[cnt2].nxt=head2[u];head2[u]=cnt2;} ll max(ll a,ll b){return a<b?b:a;} void dij(){ memset(d,0x3f,sizeof(d)); d[1]=0;q.push(mp(0,1)); while(!q.empty()){ int x=q.top().second;q.pop(); if(v[x])continue;v[x]=1; for(int i=head[x];i;i=e[i].nxt){ int y=e[i].v,z=e[i].w; if(d[y]>d[x]+z){ d[y]=d[x]+z; q.push(mp(-d[y],y)); } } } } void dfs(int x){ v[x]=1; for(int i=head2[x];i;i=e2[i].nxt){ int y=e2[i].v; if(v[y])continue; dfs(y);w[x]+=w[y]; } ans=max(ans,(ll)w[x]*(d[x]-t)); } int main(){ scanf("%d%d%d",&n,&m,&t); for(int i=1;i<=n;i++)scanf("%lld",&w[i]); for(int i=1,u,v,w;i<=m;i++){ scanf("%d%d%d",&u,&v,&w); add(u,v,w);add(v,u,w); } dij(); //建最短路树 memset(v,0,sizeof(v)); for(int i=1;i<=n;i++){ for(int j=head[i];j;j=e[j].nxt){ int y=e[j].v,z=e[j].w; if(d[y]==d[i]+z && !v[y]) v[y]=1,add2(i,y,z),add2(y,i,z); } } memset(v,0,sizeof(v)); dfs(1); printf("%lld",ans); }