Luogu P5201 [USACO19JAN]Shortcut 最短路树???

最短路树。。。开眼界了。。。之前想也没想过。。。。


先跑出来1到每个点最短路,然后建树时要标记点的入度,否则会多连边。。。然后深搜时更新新答案就是

#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
#define R register int
#define mp make_pair 
const int N=10010,M=50010;
using namespace std;
inline int g() {
    R ret=0,fix=1; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-1:fix; 
    do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret*fix;
}
int n,m,t,cnt;
int vr[M<<1],nxt[M<<1],w[M<<1],fir[N];
long long sz[N],d[N],ans,c[N];
bool vis[N];
inline void add(int u,int v,int ww)  {vr[++cnt]=v,w[cnt]=ww,nxt[cnt]=fir[u],fir[u]=cnt;}
int vv[M<<1],nn[M<<1],ww[M<<1],ff[N];
inline void aadd(int u,int v,int w) {vv[++cnt]=v,ww[cnt]=w,nn[cnt]=ff[u],ff[u]=cnt;}
priority_queue<pair<long long,int> > q;
inline void dijk() {
    memset(d,0x3f,sizeof(long long)*(n+2)); d[1]=0; q.push(mp(0,1));
    while(q.size()) {
        R u=q.top().second; q.pop(); if(vis[u]) continue; vis[u]=true;
        for(R i=fir[u];i;i=nxt[i]) { R v=vr[i];
            if(d[v]>d[u]+w[i]) d[v]=d[u]+w[i],q.push(mp(-d[v],v));
        }
    }
}
void dfs(int u) { vis[u]=true; 
    for(R i=ff[u];i;i=nn[i]) { R v=vv[i];
        if(vis[v]) continue; dfs(v); sz[u]+=sz[v];
    } ans=max(sz[u]*(d[u]-t),ans);//,cout<<u<<" "<<sz[u]<<" "<<d[u]<<" "<<t<<" "<<sz[u]*(d[u]-t)<<endl;
}
signed main() {
    n=g(),m=g(),t=g(); for(R i=1;i<=n;++i) sz[i]=g(); for(R i=1,u,v,w;i<=m;++i) u=g(),v=g(),w=g(),add(u,v,w),add(v,u,w); cnt=0;
    dijk(); memset(vis,false,sizeof(vis)); for(R u=1;u<=n;++u) for(R i=fir[u];i;i=nxt[i]) 
        if(d[vr[i]]==d[u]+w[i]&&!vis[vr[i]]) vis[vr[i]]=true,aadd(u,vr[i],w[i]),aadd(vr[i],u,w[i]);
    memset(vis,false,sizeof(bool)*(n+2)); dfs(1); printf("%lld\n",ans);
}

2019.04.25

猜你喜欢

转载自www.cnblogs.com/Jackpei/p/10765872.html
今日推荐