求图从s出发的最短路径树的边权总和最小。
在跑dijkstra时候,保证每个点的父边权值尽量小就可以了。
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <string>
#include <list>
#include <cstdlib>
#include <queue>
#include <stack>
#include <cmath>
#include <bitset>
#include <cassert>
#define ALL(a) a.begin(), a.end()
#define clr(a, x) memset(a, x, sizeof a)
#define X first
#define Y second
#define pb push_back
#define lowbit(x) (x&(-x))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define rep1(i,x,y) for(int i=x;i<=y;i++)
#define rep(i,n) for(int i=0;i<(int)n;i++)
using namespace std;
const double eps = 1e-10;
typedef long long LL;
typedef long long ll;
typedef pair<int, int> pii;
const int oo =0x3f3f3f3f;
const ll inf = 1e15;
const int maxn = 3e5 + 100;
struct edge{
int u,v,cap,id;
}a[maxn*2];
int cnt ,head[maxn] , next[maxn*2];
void init(){
cnt = 0;
memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int w ,int id){
edge& te = a[++cnt];
te.u = u, te.v = v; te.cap = w; te.id = id;
next[cnt] = head[u];
head[u] = cnt;
}
int n,m,s;
struct node{
int u; ll d;
node(int x=0,ll y=0):u(x),d(y){}
bool operator<(const node& rhs)const{
return d > rhs.d;
}
};
ll d[maxn];
int p[maxn];
bool vis[maxn];
priority_queue<node> Q;
int main()
{
init();
scanf("%d %d",&n,&m);
int x,y,z;
rep1(i,1,m) scanf("%d %d %d",&x,&y,&z),addedge(x,y,z,i),addedge(y,x,z,i);
scanf("%d",&s);
rep1(i,1,n) d[i] = inf; d[s] = 0;
memset(vis,false,sizeof(vis));
Q.push(node(s,d[s]));
while(!Q.empty()){
node x = Q.top(); Q.pop();
int u = x.u;
if(vis[u]) continue;
vis[u] = true;
for(int i = head[u]; i!=-1; i = next[i]){
edge& e = a[i];
if(d[e.v] > d[u] + e.cap){
d[e.v] = d[u] + e.cap;
p[e.v] = i;
Q.push(node(e.v,d[e.v]));
}
else if(d[e.v] == d[u] + e.cap && e.cap < a[p[e.v]].cap){
p[e.v] = i;
}
}
}
ll all = 0; rep1(i,1,n)if(i!=s) all+=a[p[i]].cap;
printf("%I64d\n",all);
rep1(i,1,n)if(i!=s){
if(i > 1) printf(" ");
printf("%d",a[p[i]].id);
}
return 0;
}