P5304 [GXOI/GZOI2019]旅行者(最短路/乱搞)

luogu

bzoj

Orz自己想出神仙正解的sxy

描述略

直接把所有起点推进去跑dijkstra...

并且染色,就是记录到这个点的最短路是由哪个起点引导出来的

然后再把所有边反指跑一次...

之后枚举每一条边两边的点不同色就可以更新答案

这个可能少有的代码比说得清楚...

 1 #include<cstdio>
 2 #include<queue>
 3 #include<algorithm>
 4 using std::min;
 5 using std::priority_queue;
 6 typedef long long lint;
 7 const int N=100011,M=1000011;
 8 template<typename tp>inline void read(tp &kk)
 9 {
10     tp ret=0,f=1;char ch=getchar();
11     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
12     while(ch>='0'&&ch<='9'){ret=ret*10+ch-'0';ch=getchar();}
13     kk=ret*f;
14 }
15 int n,m,k;
16 struct sumireko{int to,ne;lint v;}e[M];
17 int he[N],ecnt;
18 void addline(int f,int t,lint v)
19 {
20     if(f==t) return;
21     e[++ecnt].to=t;
22     e[ecnt].ne=he[f];
23     e[ecnt].v=v;
24     he[f]=ecnt;
25 }
26 
27 int X[M],Y[M],l[N];lint V[M];
28 lint d[2][N];int fa[2][N];
29 struct shino{
30     lint di;int id;
31     shino(){}
32     shino(int ii,lint dd){id=ii,di=dd;}
33     bool friend operator < (shino a,shino b){return a.di>b.di;}
34 }g;
35 priority_queue<shino>q;
36 bool vv[N];
37 void dijkstra(lint *dis,int *c)
38 {
39     for(int i=1;i<=n;i++) dis[i]=0x3f3f3f3f3f3f3f3f;
40     for(int i=1;i<=k;i++) dis[l[i]]=0,c[l[i]]=l[i],q.push(shino(l[i],0));
41     while(!q.empty())
42     {
43         g=q.top();
44         q.pop();
45         int x=g.id;
46         vv[x]=1;
47         for(int i=he[x],t;i;i=e[i].ne)
48         {
49             t=e[i].to;
50             if(vv[t]) continue;
51             if(dis[t]>dis[x]+e[i].v)
52             {
53                 dis[t]=dis[x]+e[i].v;
54                 c[t]=c[x];
55                 q.push(shino(t,dis[t]));
56             }
57         }
58     }
59 }
60 
61 
62 void clr(){for(int i=1;i<=n;i++) he[i]=0,vv[i]=0;ecnt=0;}
63 int xi,yi,vi,T;
64 int main()
65 {
66     read(T);
67     while(T--)
68     {
69         read(n),read(m),read(k);
70         for(int i=1;i<=m;i++) read(X[i]),read(Y[i]),read(V[i]),addline(X[i],Y[i],V[i]);
71         for(int i=1;i<=k;i++) read(l[i]);
72         dijkstra(d[0],fa[0]);
73         clr();
74         for(int i=1;i<=m;i++) addline(Y[i],X[i],V[i]);
75         dijkstra(d[1],fa[1]);
76         lint ans=0x3f3f3f3f3f3f3f3f;
77         for(int i=1;i<=m;i++)
78         {
79             xi=X[i],yi=Y[i],vi=V[i];
80             if(fa[0][xi]&&fa[1][yi]&&(fa[0][xi]^fa[1][yi]))
81             {
82                 ans=min(ans,d[0][xi]+vi+d[1][yi]);
83             }
84         }
85         printf("%lld\n",ans);
86         clr();
87     }
88     return 0;
89 }
哭唧唧

 

转载于:https://www.cnblogs.com/rikurika/p/gxoi3.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值