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\n"); 79 flag = 1; 80 break; 81 } 82 } 83 if (!flag) printf("No\n"); 84 } 85 return 0; 86 }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步