51nod1326 遥远的旅途(spfa+dp)

题意:
给出一个无向图,问从1到n是否存在一条长度为L的路径。
n,m<=50,1<=路径长度<=10000,L<=10^18

思路:
改变一下思路,我们发现,假设从起点1走到终点N有一条路径的长度为a,假设它再往一条与终点相连的长为b的路径反复走无数次后使得路径长度到达了T,那么一定有(T-a)%(2*k)==0**T%(2*k)=a%(2*k),所以我们只需要看是否从1到N存在一条路径长度为d,使得d%(2*k)=t%(2*k)
因为这个题目和模数有关,所以我们要把取摸的结果写入状态.
dp[i][j]表示处于i节点,从一号点到i号点的花费和%(2*k)(选择的边权)等与k的最小花费.
那么转移就是: dp[to][(j+quan)%mod]=min(dp[now][j]+quan)
因为具有后效性,所以需要spfa.

 1 //这道题较多的参考了晚上的解法,在看懂之后自己又写了一遍
 2 //链接:https://blog.csdn.net/qq_33229466/article/details/77131289
 3 #include<cstdio>
 4 #include<queue>
 5 #include<string.h>
 6 using namespace std;
 7 typedef long long LL;
 8 
 9 const int maxn = 50 + 5, maxm = 2e4 + 5;
10 int n, m, num, head[maxn];
11 LL t, dp[maxn][maxm], inf = 2000000000000000000;
12 bool vis[maxn][maxm];
13 
14 struct node { 
15     int to, w, next;
16 }edge[maxn * 2];
17 queue<pair<int, int>>q;
18 
19 void add_edge(int u, int v, int w)
20 {
21     edge[++num].to = v; 
22     edge[num].w = w; 
23     edge[num].next = head[u]; 
24     head[u] = num;
25 }
26 
27 void spfa(int mod)
28 {
29     q.push(make_pair(1,0)); vis[1][0] = 1;
30     while (!q.empty())
31     {
32         pair<int,int> u = q.front(); q.pop();
33         int x = u.first, y = u.second;
34         for (int i = head[x]; i; i = edge[i].next)
35             if (dp[x][y] + edge[i].w < dp[edge[i].to][(y + edge[i].w) % mod])
36             {
37                 int nx = edge[i].to, ny = (y + edge[i].w) % mod;
38                 dp[nx][ny] = dp[x][y] + edge[i].w;
39                 if (!vis[nx][ny]) {
40                     q.push(make_pair(nx, ny));
41                     vis[nx][ny] = 1;
42                 }
43             }
44         vis[x][y] = 0;
45     }
46 }
47 
48 int main()
49 {
50     int kase;
51     scanf("%d", &kase);
52     while (kase--)
53     {
54         memset(head, 0, sizeof(head));
55         scanf("%d%d%lld", &n, &m, &t);
56         num = 0;
57         for (int i = 1; i <= m; i++)
58         {
59             int x, y, w;
60             scanf("%d%d%d", &x, &y, &w);
61             add_edge(x, y, w);
62             add_edge(y, x, w);
63         }
64         int flag = 0;
65         for (int i = 1; i <= num; i += 2)
66             if (edge[i].to == 1 || edge[i + 1].to == 1)
67             {
68                 int w = edge[i].w * 2;
69                 for (int j = 1; j <= n; j++) {
70                     for (int k = 0; k < w; k++) {
71                         dp[j][k] = inf;
72                     }
73                 }
74                 dp[1][0] = 0;
75                 spfa(w);
76                 if (dp[n][t%w] <= t)
77                 {
78                     printf("Yes
");
79                     flag = 1;
80                     break;
81                 }
82             }
83         if (!flag) printf("No
");
84     }
85     return 0;
86 }
原文地址:https://www.cnblogs.com/romaLzhih/p/9489832.html