1. 程式人生 > >P5122 [USACO18DEC]Fine Dining 最短路

P5122 [USACO18DEC]Fine Dining 最短路

urn queue spa air dig 一個 stream top ++

先跑一遍n為起點最短路,再新開一個點,向有幹草垛的點連一根邊權為d[u]-w的有向邊(很重要。。我當時連的無向邊,然後我死了。),相當於用價值抵消一部分邊權,

然後以這個新的點為起點跑最短路就好了。。。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
#define pc(x) putchar(x)
#define R register int
using namespace std;
const int N=50010,M=100010;
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,k,cnt; int vr[M<<1],nxt[M<<1],w[M<<1],fir[N],d[N],f[N]; bool vis[N]; priority_queue<pair<int
,int> > q; inline void add(int u,int v,int ww) {vr[++cnt]=v,w[cnt]=ww,nxt[cnt]=fir[u],fir[u]=cnt;} inline void dijk() { memset(d,0x3f,sizeof(int)*(n+2)); d[n]=0,q.push(make_pair(0,n)); 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(make_pair(-d[v],v)); } } } inline void dijk2() { memset(f,0x3f,sizeof(int)*(n+3)); f[n+1]=0,q.push(make_pair(0,n+1)); memset(vis,false,sizeof(bool)*(n+3)); 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(f[v]>f[u]+w[i]) f[v]=f[u]+w[i],q.push(make_pair(-f[v],v)); } } } signed main() { n=g(),m=g(),k=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); dijk(); for(R i=1,u,w;i<=k;++i) u=g(),w=g(),add(n+1,u,d[u]-w); dijk2(); for(R i=1;i<n;++i) f[i]<=d[i]&&d[i]!=0x3f3f3f3f?(pc(1),pc(\n)):(pc(0),pc(\n)); }

2019.04.24

P5122 [USACO18DEC]Fine Dining 最短路