原题: http://acm.zjnu.edu.cn/CLanguage/showproblem?problem_id=2244
题意:
n个点,每个点上有ci头牛,m条无向边,总时间定义为所有牛会走到点1的总时间。现在从点1连一条t的边到其他点,问最多可以节省多少总时间。
每头牛会走原来的最优路径,如果有多条则走字典序最小的那条。此时遇到了新建的边才可能走这条边。
解析:
这题虽然是个水题,但是我却。。
首先dijkstra求每个点到点1的距离,做完后对点u,如果存在一条边(u,v)且dis[v]+(u,v)=dis[u],那么说明u走到v是最优路径之一。那么,在这些点取一个min就是前缀了。
这样会生成一棵树,搜一遍后得出每个点会有多少牛经过,算一下即可。
我没有考虑到重边的情况,就是搜多少牛经过的时候重边就算了多次,这里加个vis即可。
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for( int i=a;i<=b;i++)
#define LL long long
int read(){ int ans=0; char last=' ',ch=getchar();
while(ch<'0' || ch>'9')last=ch,ch=getchar();
while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
if(last=='-')ans=-ans; return ans;
}
LL read_LL(){ LL ans=0; char last=' ',ch=getchar();
while(ch<'0' || ch>'9')last=ch,ch=getchar();
while(ch>='0' && ch<='9')ans=ans*10ll+(LL)(ch-'0'),ch=getchar();
if(last=='-')ans=-ans; return ans;
}
#define pill pair<int,int>
const int maxn=2e4+4,maxm=2e5+5;
int n,m;
LL t;
struct node{
node(){}
node(int id,LL val):id(id),val(val){}
int id;LL val;
bool operator<(const node &r)const{
return val>r.val;
}
};
int pre[maxn],vis[maxn];
LL dis[maxn];
int head[maxn],to[maxm],nex[maxm],now;
LL val[maxm];
void add(int a,int b,LL v){
nex[++now]=head[a];head[a]=now;to[now]=b;val[now]=v;
}
priority_queue<node>Q;
void dij(){
for(int i=0;i<=n;i++)dis[i]=1e18;
dis[1]=0;
Q.push(node(1,0));
while(!Q.empty()){
int idx=Q.top().id;Q.pop();
if(vis[idx])continue;
vis[idx]=1;
for(int i=head[idx];i;i=nex[i]){
int v=to[i];
if(vis[v])continue;
if(dis[idx]+val[i]<dis[v]){
dis[v]=dis[idx]+val[i];
Q.push(node(v,dis[v]));
}
}
}
}
LL num[maxn];
LL siz[maxn];
LL ans;
LL dfs(int p){
vis[p]=1;
siz[p]=num[p];
for(int i=head[p];i;i=nex[i]){
int v=to[i];
if(pre[v]==p){
if(!vis[v])
siz[p]+=dfs(v);
}
}
return siz[p];
}
int main(){
n=read(),m=read(),t=read_LL();
rep(i,1,n)num[i]=read_LL();
rep(i,1,m){
int a=read(),b=read();LL v=read_LL();
add(a,b,v);
add(b,a,v);
}
dij();
memset(pre,0x3f,sizeof(pre));
for(int i=1;i<=n;i++){
for(int j=head[i];j;j=nex[j]){
int v=to[j];
if(dis[v]==dis[i]+val[j]&&i<pre[v])pre[v]=i;
}
}
memset(vis,0,sizeof(vis));
dfs(1);
rep(i,1,n){
if(t<dis[i]){
ans=max(ans,(dis[i]-t)*siz[i]);
}
}
printf("%lld\n",ans);
return 0;
}