题意:一个中心原点1,给你n个点,m条边,问你从1到2-n的每一个点,加上从2-n返回1点的距离总和的最小值是多少?
想法:比较好想,去:单源最短路,从1开始,所有点自动跑完,反向建边,就不需要从枚举每一个2-n的点到1的最短路。求和即可。
#include<iostream> #include<cstring> #include<cstdio> #include<queue> #define inf 0x7fffffff using namespace std; const int nodes=1000000+50; const int edges=1000000+50; struct node { int v,w,next; }e[edges]; int head[nodes],cnt,sum; int n,m; int a[edges],b[edges],c[edges]; void Init() { memset(head,-1,sizeof(head)); cnt=0; } void add(int u,int v,int w) { e[cnt].v=v; e[cnt].w=w; e[cnt].next=head[u]; head[u]=cnt++; } void spfa() { queue<int>q; while(!q.empty()) q.pop(); int dis[nodes]; bool vis[nodes]; for(int i=1;i<=n;i++) { dis[i]=inf; vis[i]=0; } dis[1]=0; vis[1]=1; q.push(1); while(!q.empty()) { int u=q.front(); q.pop(); vis[u]=0; for(int i=head[u];i+1;i=e[i].next) { int v=e[i].v; if(dis[v]>dis[u]+e[i].w) { dis[v]=dis[u]+e[i].w; if(!vis[v]) { vis[v]=1; q.push(v); } } } } for(int i=1;i<=n;i++) sum+=dis[i]; } int main() { int test; scanf("%d",&test); while(test--) { Init(); scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { scanf("%d%d%d",&a[i],&b[i],&c[i]); add(a[i],b[i],c[i]); } sum=0; spfa(); Init(); for(int i=1;i<=m;i++) { add(b[i],a[i],c[i]); } spfa(); printf("%d\n",sum); } return 0; }