【SDUTOJ 3309】 乱七八糟的图
题意翻译过来就是找构成最短路需要的最短的边长 因为存在一些最短路会共用一些边 所以求一遍最短路 然后遍历所有点 判断与该点连的边是否是构成最短路所需的边 把满足条件的边中最短的加入即可 即为到达该点所需要的边
代码如下:
#include <bits/stdc++.h> #define ll long long using namespace std; typedef struct Edge { int v,w,next; }Edge; Edge eg[666666]; int head[33333]; ll dis[33333]; bool vis[33333]; int tp; void spfa(int u) { memset(dis,-1,sizeof(dis)); memset(vis,0,sizeof(vis)); dis[u] = 0; deque <int> q; int i,v,w; q.push_front(u); while(!q.empty()) { u = q.front(); q.pop_front(); vis[u] = 0; for(i = head[u]; i != -1; i = eg[i].next) { v = eg[i].v; w = eg[i].w; if(dis[v] == -1 || dis[v] > dis[u]+w) dis[v] = dis[u]+w; else continue; if(vis[v]) continue; if(q.empty()) q.push_front(v); else if(dis[v] < dis[q.front()]) q.push_front(v); else q.push_back(v); vis[v] = 1; } } } void Add(int u,int v,int w) { eg[tp].v = v; eg[tp].w = w; eg[tp].next = head[u]; head[u] = tp++; } int main() { int n,m,st,u,v,w,i,j; ll sum,mm; while(~scanf("%d %d",&n,&m)) { memset(head,-1,sizeof(head)); tp = 0; while(m--) { scanf("%d %d %d",&u,&v,&w); Add(u,v,w); Add(v,u,w); } scanf("%d",&st); spfa(st); sum = 0; for(i = 1; i <= n; ++i) { if(i == st) continue; mm = 0; for(j = head[i]; j != -1; j = eg[j].next) { if(dis[i] == dis[eg[j].v] + eg[j].w) { if(!mm || mm > eg[j].w) mm = eg[j].w; } } sum += mm; } printf("%lld\n",sum); } return 0; }