codeforces round# 303(div2 E)(思路图)

求图从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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值