逃生

【题目描述】
小 J 在一次旅行中感染了一只可以分裂细菌,这种细菌在出现一分钟后会分裂成两只
相同重量的细菌,其中一只不再分裂,另一只在一分钟后继续分裂。小 J 想尽快找到杀菌
草药,然而可供行走的路并不多。山里共有 n 个水池与 m 条路,每条路连接两个水池,
走过这条道路需要花费一定的时间。小 J 感染时在 s 号水池,杀菌草药生长在 t 号水池里。
小 J 每经过一个水池时都要喝一口水来补充体力,但是细菌也会产生变化:现存所有细菌
都会合体为一只,重量为所有细菌重量之和,合体一分钟后继续分裂。然而,小 J 并不知
道这一点,每经过一个水池,他依然会去喝水。你需要为小 J 画出一条从 s 号水池到 t 号
水池的路线,使得小 J 到达 t 号水池时身上的细菌重量最小。数据保证有且只有一组解。
【输入格式】
第一行四个整数 n m s t
接下来 m 行,每行三个整数 l r w,表示 l 号水池与 r 号水池间有一条道路,花费为 w 分
钟(喝水不花费时间)。同一对 l r 之间可能有多条道路
【输出格式】
第一行一个整数 k,表示路线长度
接下来一行 k 个整数,依次表示你画出的路线中经过的每个点
【样例输入】
4 4 1 4
1 2 0
1 3 2
3 4 1
2 4 4
【样例输出】
3
1 2 4
【数据范围】
30%的数据保证 n ≤ 50;w ≤ 10
100%的数据保证 2 ≤ n ≤ 10000;1 ≤ m ≤ 30000;0 ≤ w ≤ 1000;s ≠ t;l ≠ r

很显然一下就能转换成 d[v]=d[u]*(w[u, v]+1)的等式。

但是对于这种数据,显然是会爆long long的

于是用对数离散,因为log(nm)=logn+logm

于是就变成了普通的SPFA

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 #include<queue>
 7 using namespace std;
 8 struct Node
 9 {
10   int next,to;
11   double dis;
12 }edge[600001];
13 int head[100001],num,n,m,s,t;
14 int len[100001],pre[100001];
15 double dist[100001];
16 bool vis[100001];
17 void add(int u,int v,double w)
18 {
19   num++;
20   edge[num].next=head[u];
21   head[u]=num;
22   edge[num].to=v;
23   edge[num].dis=w;
24 }
25 void SPFA(int S)
26 {int i;
27   queue<int>Q;
28   for (i=0;i<=n;i++)
29     dist[i]=1000000000.0;
30   len[S]=1;dist[S]=0;
31   Q.push(S);
32   while (Q.empty()==0)
33     {
34       int u=Q.front();
35       Q.pop();
36       vis[u]=0;
37       for (i=head[u];i;i=edge[i].next)
38     {
39       int v=edge[i].to;
40       if (dist[v]>dist[u]+edge[i].dis)
41         {
42           dist[v]=dist[u]+edge[i].dis;
43           pre[v]=u;
44           len[v]=len[u]+1;
45           if (vis[v]==0)
46         {
47           Q.push(v);
48           vis[v]=1;
49         }
50         }
51     }
52     }
53 }
54 void print(int S,int x)
55 {
56   if (x!=S)
57     print(S,pre[x]);
58       printf("%d ",x);
59 }
60 int main()
61 {int u,v,i;
62   double d;
63   cin>>n>>m>>s>>t;
64   for (i=1;i<=m;i++)
65     {
66       scanf("%d%d%lf",&u,&v,&d);
67       add(u,v,log2(d+1));
68       add(v,u,log2(d+1));
69     }
70   SPFA(s);
71   cout<<len[t]<<endl;
72   print(s,t);
73 }

 

posted @ 2017-10-30 16:06  Z-Y-Y-S  阅读(220)  评论(0编辑  收藏  举报