大晚上的打代码确实挺心累的,本来想这题搞完就睡,没想到搞了好久
题目将从某点出发的所有最短路方案中,选择边权和最小的最短路方案,称为最短生成树。
题目要求一颗最短生成树,输出总边权和与选取边的编号。
1.测试数据比较强 最大值要放很大 const ll inf=0x7fffffffffffff;(13个)
2. typedef pair<long long, int> P;
用到优先队列 priority_queue<P,vector<P>,greater<P> > q;
本来是可以重载小于号 ,但重载后就超时了,还是去掉用默认的,即P在q中默认按P.first来比
/*struct cmp{
bool operator() ( P a, P b ){
return a.first< b.first; }
};*/
3.memset是按字节来填的,不能用来赋最大值,可以用fill 替代 fill(d,d+n+1,inf);格式和sort有点类似
4.主要算法把 迪杰斯特拉改了一下c【】用来存与该点绑定的边的cost,s用来存绑定的边
值得一提的是去掉了flag数组,目的是在最短路不变的情况下更新是否有更小权值的边
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<functional>
#define N 300005
#define ll long long
using namespace std;
const ll inf=0x7fffffffffffff;
struct edge
{
int to,cost,id;
edge(int t,int c,int d): to(t),cost(c),id(d){}
};
typedef pair<long long, int> P;
/*struct cmp{
bool operator() ( P a, P b ){
return a.first< b.first; }
};*/
vector<edge>G[N];
ll d[N],c[N];//c代表与该点绑定的边的cost
int m,n,s[N];//存与该节点绑定的边
void dij(int u)
{
fill(d,d+n+1,inf);
fill(c,c+n+1,inf);
d[u]=0;
priority_queue<P,vector<P>,greater<P> > q;
q.push(P(d[u],u));
while(!q.empty())
{
P p=q.top();
q.pop();
int v=p.second;
//if(d[v] < p.first) continue;
for(int i=0;i<G[v].size();i++)
{
edge e=G[v][i];
if(d[e.to] >d[v] + e.cost )
{
d[e.to]= d[v] + e.cost;
s[e.to]= e.id;
c[e.to]= e.cost;
q.push(P(d[e.to],e.to));
}
else if(d[e.to] ==d[v] + e.cost && c[e.to]>e.cost)
{
s[e.to]= e.id;
c[e.to]= e.cost;
}
}
}
}
int main(){
int u,v,co;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
scanf("%d%d%d",&u,&v,&co);
G[u].push_back(edge(v,co,i));
G[v].push_back(edge(u,co,i));
}
scanf("%d",&u);
dij(u);
ll sum=0;
for(int i=1;i<=n;i++){
if(i!=u) sum+=c[i];
}
cout<<sum<<endl;
for(int i=1;i<=n;i++){
if(i!=u) cout<<s[i]<<' ';
}
return 0;
}