今天集训学长没有给负环的题,所以一下子全都用Dijkstra做了,SPFA都没练习到,所以专门把这道不卡SPFA的题拿来练练
题目含义
求1到其他点的最短距离之和,加上其他点到1的最短距离之和
题目分析
求1到其他点的最短距离之和,也就是单源最短路径,Dijkstra和SPFA应该都行
而其他点到1的最短距离之和,实际上还是求的1到其他点的距离,不过由于路径两个方向的长度不一样,所以反向建树就好了
题目代码
#include<iostream> #include<stdio.h> #include<string.h> #include<queue> using namespace std; const int maxn=1e6+7; const int INF=0x3f3f3f3f; typedef long long LL; int head[maxn],dis[maxn]; int tot,u[maxn],v[maxn],w[maxn]; bool vis[maxn]; LL ans; int t,n,m; struct edge{ int to,w,next; }e[maxn]; struct node{ int pos,dis; bool operator<(const node &x)const{ return dis>x.dis; } }; void add(int u,int v,int w){ e[tot].to=v; e[tot].w=w; e[tot].next=head[u]; head[u]=tot++; } void init(){ tot=0; memset(dis,INF,sizeof(dis)); memset(head,-1,sizeof(head)); memset(vis,false,sizeof(vis)); } void Dijkstra(){ dis[1]=0; priority_queue<node>q; q.push((node){1,0}); while(!q.empty()){ node temp=q.top();q.pop(); int u=temp.pos; if(vis[u])continue; vis[u]=true; for(int i=head[u];i!=-1;i=e[i].next){ int v=e[i].to; if(dis[v]>dis[u]+e[i].w){ dis[v]=dis[u]+e[i].w; if(!vis[v])q.push((node){v,dis[v]}); } } } } int main(){ scanf("%d",&t); while(t--){ scanf("%d%d",&n,&m); ans=0; init(); for(int i=1;i<=m;i++){ scanf("%d%d%d",&u[i],&v[i],&w[i]); add(u[i],v[i],w[i]); } Dijkstra(); for(int i=2;i<=n;i++) ans+=dis[i]; init(); for(int i=1;i<=m;i++){ add(v[i],u[i],w[i]); } Dijkstra(); for(int i=2;i<=n;i++) ans+=dis[i]; printf("%lld ",ans); } return 0; }
真的是Dijkstra做多了,一遍就过了
#include<iostream> #include<stdio.h> #include<string.h> #include<queue> using namespace std; const int maxn=1e6+7; const int INF=0x3f3f3f3f; typedef long long LL; int head[maxn],dis[maxn],num[maxn]; bool vis[maxn]; LL ans; int t,n,m,tot,u[maxn],v[maxn],w[maxn]; struct edge{ int to,w,next; }e[maxn]; void add(int u,int v,int w){ e[tot].to=v; e[tot].w=w; e[tot].next=head[u]; head[u]=tot++; } void init(){ tot=0; memset(head,-1,sizeof(head)); memset(vis,false,sizeof(vis)); memset(dis,INF,sizeof(dis)); memset(num,0,sizeof(num)); } bool SPFA(){ queue<int>q; dis[1]=0;num[1]++;vis[1]=true; q.push(1); while(!q.empty()){ int u=q.front();q.pop(); vis[u]=false; for(int i=head[u];i!=-1;i=e[i].next){ int v=e[i].to; if(dis[v]>dis[u]+e[i].w){ dis[v]=dis[u]+e[i].w; if(!vis[v]){ vis[v]=true; num[v]++; q.push(v); if(num[v]>n)return false; } } } } return true; } int main(){ scanf("%d",&t); while(t--){ scanf("%d%d",&n,&m); ans=0; init(); for(int i=1;i<=m;i++){ scanf("%d%d%d",&u[i],&v[i],&w[i]); add(u[i],v[i],w[i]); } SPFA(); for(int i=2;i<=n;i++) ans+=dis[i]; init(); for(int i=1;i<=m;i++){ add(v[i],u[i],w[i]); } SPFA(); for(int i=2;i<=n;i++) ans+=dis[i]; printf("%lld ",ans); } return 0; }
我果然写的不熟练,照着模板写的
还得再练练