乱七八糟的图
Time Limit: 4000ms Memory limit: 65536K 有疑问?点这里^_^
题目描述
给一个连通无向图,图有n个顶点m条边,可能会有重边,无自环。然后给一个出发点st,现在这个st到其他每一个顶点都有一个最短距离。然后,让你删除一些边,剩下的边构成了一个新连通无向图,要求在新图中,出发点st到其他任何一个顶点的最短距离跟删边之前的最短距离保持不变,而且要求剩下的所有边的总长度最短。求出这个总长度。
输入
多组输入。每组测试数据第一行为两个整数
n(1<=n<=3*10^4)
和
m(1<=m<=3*10^5).
接下来
m
行,每行包括三个整数
u,v,w.(1<=u,v<=n,1<=w<=10^9),
表示顶点
u
和
v
之间有一条长度为
w
的无向边。最后一行给出一个整数
st
,
(1<=st<=n)
表示出发点。
输出
每组测试数据输出一个整数表示最短的总长度。
示例输入
3 3 1 2 1 2 3 1 1 3 2 3 4 4 1 2 1 2 3 1 3 4 1 4 1 2 4
示例输出
2 4
提示
来源
scf0920
示例程序
题目链接: 点击打开链接
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<string.h>
#include<queue>
#define N 30001
#define LL long long int
#define INF 0x3f3f3f3f
using namespace std;
struct node {
int x;
int y;
int z;
int next;
}q[N<<6];
int head[N],v[N];
LL dis[N];
int n,m;
int cnt;
void add(int x,int y,int z){
q[cnt].x = x;
q[cnt].y = y;
q[cnt].z = z;
q[cnt].next = head[x];
head[x] = cnt++;
}
LL min(LL a,LL b){
return a>b?b:a;
}
void spfa(int st){
for(int i=1;i<=n;i++){
dis[i] = INF;
v[i] = 0;
}
queue<int>p;
while(!p.empty()){
p.pop();
}
dis[st] = 0;
v[st] = 1;
p.push(st);
while(!p.empty()){
st = p.front();
p.pop();
v[st] = 0;
for(int i=head[st];i!=-1;i=q[i].next){
if(dis[q[i].y]>dis[q[i].x]+q[i].z){
dis[q[i].y] = dis[q[i].x] + q[i].z;
if(v[q[i].y] == 0){
p.push(q[i].y);
v[q[i].y] = 1;
}
}
}
}
}
LL getsum(int xx){
LL sum = INF;
for(int i=head[xx];i!=-1;i=q[i].next){
if(dis[q[i].y]+q[i].z == dis[xx]){
sum = min(sum,q[i].z);
}
}
return sum;
}
int main(){
while(scanf("%d%d",&n,&m)!=EOF){
cnt = 0;
memset(head,-1,sizeof(head));
int x,y,z;
for(int i=0;i<m;i++){
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
add(y,x,z);
}
int k;
scanf("%d",&k);
spfa(k);
LL sum = 0;
for(int i=1;i<=n;i++){
if(i!=k){
sum += getsum(i);
}
}
printf("%lld\n",sum);
}
return 0;
}