题解 P5201 【[USACO19JAN]Shortcut】
发现自己难题做多了,反不会简单题。
题目大意
给定一个有
解题思路
从结点
建最短路树时,由于奶牛会在路径长度相等的情况下走字典序更小的路径,所以我的方法是 从小到大 枚举起点
注意
请使用 long long 。
代码展示
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
const int maxn=100010;
typedef long long ll;
ll n,m,c[maxn],T,cur,h[maxn],nxt[maxn],p[maxn],w[maxn],u,v,t;
ll dist[maxn],siz[maxn],ans;
bool tf[maxn];
struct node
{
ll id,v;
bool operator<(node x)const{return v>x.v;}
};
priority_queue<node>q;
vector<int>g[10010];
void add_edge(ll u,ll v,ll t)
{
cur++;
nxt[cur]=h[u];
h[u]=cur;
p[cur]=v;
w[cur]=t;
}
bool f[maxn];
void dfs(int x)
{
siz[x]=c[x];f[x]=true;
for(vector<int>::iterator it=g[x].begin();it!=g[x].end();it++)
if(!f[*it])dfs(*it),siz[x]+=siz[*it];
ans=max(ans,siz[x]*(dist[x]-T));
}
int main()
{
scanf("%lld%lld%lld",&n,&m,&T);
for(int i=1;i<=n;i++)scanf("%lld",c+i);
while(m--)scanf("%lld%lld%lld",&u,&v,&t),add_edge(u,v,t),add_edge(v,u,t);
q.push({1,0});
while(!q.empty())
{
node x=q.top();q.pop();
if(tf[x.id])continue;
tf[x.id]=true;dist[x.id]=x.v;
for(int j=h[x.id];j;j=nxt[j])q.push({p[j],x.v+w[j]});
}
memset(tf,0,sizeof tf);
for(int i=1;i<=n;i++)for(int j=h[i];j;j=nxt[j])
if(dist[p[j]]==dist[i]+w[j]&&!tf[p[j]])tf[p[j]]=true,
g[i].push_back(p[j]),g[p[j]].push_back(i);
dfs(1);
printf("%lld\n",ans);
return 0;
}