bzoj5506:[gzoi2019]旅行者
阿新 • • 發佈:2019-05-04
memset register print operator std ble ++ getchar add
傳送門
正反兩邊dijkstra染色,然後枚舉一下邊,求出最小值就好啦
代碼:
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<queue> using namespace std; void read(int &x) { char ch; bool ok; for(ok=0,ch=getchar(); !isdigit(ch); ch=getchar()) if(ch=='-') ok=1; for(x=0; isdigit(ch); x=x*10+ch-'0',ch=getchar()); if(ok) x=-x; } #define rg register #define ll long long const int maxn=1e5+10;bool vis[maxn]; struct oo{int x;ll dis;}; priority_queue<oo>q;ll ans,dis[2][maxn]; bool operator<(oo a,oo b){return a.dis>b.dis;} int n,T,m,k,col[2][maxn],pre[maxn*5],nxt[maxn*5],v[maxn*5],h[maxn],cnt; int x[maxn*5],y[maxn*5],z[maxn*5],t[maxn]; void add(int x,int y,int z){pre[++cnt]=y,nxt[cnt]=h[x],h[x]=cnt,v[cnt]=z;} void dijkstra(ll *dis,int *col){ memset(vis,0,sizeof vis); for(rg int i=1;i<=k;i++)dis[t[i]]=0,col[t[i]]=t[i],q.push((oo){t[i],dis[t[i]]}); while(!q.empty()){ oo x=q.top();q.pop();if(vis[x.x])continue;vis[x.x]=1; for(rg int i=h[x.x];i;i=nxt[i]) if(!vis[pre[i]]&&dis[pre[i]]>dis[x.x]+v[i]) dis[pre[i]]=dis[x.x]+v[i],col[pre[i]]=col[x.x], q.push((oo){pre[i],dis[pre[i]]}); } } int main() { read(T); while(T--){ read(n),read(m),read(k);cnt=0;memset(h,0,sizeof h); memset(col,0,sizeof col);memset(dis,63,sizeof dis); for(rg int i=1;i<=m;i++)read(x[i]),read(y[i]),read(z[i]),add(x[i],y[i],z[i]); for(rg int i=1;i<=k;i++)read(t[i]); dijkstra(dis[0],col[0]);memset(h,0,sizeof h),cnt=0; for(rg int i=1;i<=m;i++)add(y[i],x[i],z[i]); dijkstra(dis[1],col[1]);ans=1e18; for(rg int i=1;i<=m;i++) if(col[0][x[i]]&&col[1][y[i]]&&col[0][x[i]]!=col[1][y[i]])ans=min(ans,dis[0][x[i]]+dis[1][y[i]]+z[i]); printf("%lld\n",ans); } }
bzoj5506:[gzoi2019]旅行者