SPFA 算法 + 小trick + 开longlong + 尽量别用结构体
有一道题是酱紫的,单源最短路,给你一些路,给你这些路的长度,给你修这些路的话费,求最短路和最小花费。
最短路很好求,就是用SPFA算法,值得注意的就是结构体很耗时,能不用就不用。
1.SPFA算法:求单源最短路,先把0扔进去,看看有哪些边能够被松弛,把能被松弛的边松弛掉,然后把被松弛的点扔到队列里,直到没有点能被松弛。
2.能用数组就别用结构体,不说了。。
3.注意开longlong
AC 代码:
#include <string.h> #include <stdio.h> #define INF 0x3f3f3f3f #include <queue> #define N 50005 * 5 using namespace std; int cnt,n,m; int head[N],vis[N]; struct node { int v; int next; long long val; long long t; } edge[N]; void add(int u,int v,int a,int b) { edge[cnt].t=a; edge[cnt].val=b; edge[cnt].v=v; edge[cnt].next=head[u]; head[u]=cnt++; } long long cost[N],tt[N]; void SPFA() { memset(vis,0,sizeof(vis)); memset(cost,INF,sizeof(cost)); memset(tt,INF,sizeof(tt)); queue<int>q; q.push(0); vis[0]=1; cost[0]=tt[0]=0; while (!q.empty()) { int out = q.front(); q.pop(); vis[out] = 0; for (int i = head[out]; i + 1; i = edge[i].next) { if (tt[out] + edge[i].t <= tt[edge[i].v]) { if (tt[out] + edge[i].t < tt[edge[i].v]) { tt[edge[i].v] = tt[out] + edge[i].t; cost[edge[i].v] = edge[i].val; if (!vis[edge[i].v]) { q.push(edge[i].v); vis[edge[i].v] = 1; } } else if (cost[edge[i].v]>edge[i].val) //时间相同考虑费用小的边 { if (!vis[edge[i].v]) { q.push(edge[i].v); vis[edge[i].v] = 1; } cost[edge[i].v] = edge[i].val; } } } } } int main() { int T,x,y,a,b; scanf("%d",&T); while(T--) { cnt=0; memset(head,-1,sizeof(head)); scanf("%d%d",&n,&m); for(int i=0; i<m; i++) { scanf("%d%d%d%d",&x,&y,&a,&b); add(x,y,a,b); add(y,x,a,b);//前向星建图 } SPFA(); long long sum1=0,sum2=0; for (int i = 0; i < n; i++) { sum1 += tt[i]; sum2 += cost[i]; } printf("%lld %lld ", sum1, sum2); } return 0; }