• CF 545E Paths and Trees


    题目大意:给出n个点,m条无向边,每条边有长度。求一棵树,要求树上的每个点到源点距离最小的前提下,使得树上的边的长度和最小。输出树上边的总长度,以及树上的边的序号(按输入顺序 1...m).

    思路 :单源最短路径 + 贪心 .用Dijkstra 或spfa 算法 求每个点到源点的最短路径,并在记录当前用来更新每个点最短距离的那条边(即pre[i]记录点i所对应的变)。

        若当前这条边能使得某个点到源点的距离变小则更新该点到源点的距离,并记录更新该点的边; 若当前这条边更新某节点后,使得该点到源点的距离不变(即:d[e[t].to] = d[e[t].from] + e[t].length ) 则比较这条边与当前该点所记录的边的长度大小,若这条边比改点所记录的边长度要小(即e[pre[e[t].to]].length > e[t].length),则更新改点所记录的边(pre[e[t].to] = t)。

     

    代码 :

    1. #include<stdio.h>
      #include<iostream>
      #include<string.h>
      #include<stdlib.h>
      #include<queue>
      #define INF 0x7fffffffffffffff
      #define pii pair<long long,long long> 
      using namespace std;
      long long s,n,m,pre[300002],tag[600002],u[600002],v[600002],next[600002],first[300002];
      long long sum,d[300002],w[600002];
      priority_queue<pii,vector<pii>,greater<pii> > Q;
      bool vis[300002];
      
      void input(){
      	long long i,j,a,b,c;
      	for(i=1;i<=n;i++)
      	    first[i] = -1;
      	for(i=1;i<=m;i++){
      		scanf("%I64d %I64d %I64d",&u[i],&v[i],&w[i]);
      		u[i+m] = v[i] ;
      		v[i+m] = u[i] ;
      		w[i+m] = w[i] ;
      		next[i] = first[u[i]];
      		first[u[i]] = i ;
      		next[i+m] = first[v[i]];
      		first[v[i]] = i+m ;
      	}
      	scanf("%I64d",&s);
      }
      
      void Dijkstra(){
      	long long i,j;
      	memset(vis,0,sizeof(vis));
      	memset(tag,0,sizeof(tag));
      	for(i=1;i<=n;i++)
      	    pre[i] = -1 ;
      	for(i=1;i<=n;i++)
      	    d[i] = INF;
      	d[s] = 0;
      	Q.push(make_pair(d[s],s));
      	while(!Q.empty()){
      		pii t = Q.top();
      		Q.pop(); 
      		long long x = t.second;
      		if(vis[x])
      		    continue;
      		vis[x] = true;
      		for(long long e=first[x]; e!=-1; e=next[e]){
      			if(d[v[e]] > d[x] + w[e] && d[x] < INF){
      				pre[v[e]] = e;
      				d[v[e]] = d[x] + w[e] ;
      				Q.push(make_pair(d[v[e]],v[e]));}elseif(d[v[e]]== d[x]+ w[e]&& d[x]< INF && w[pre[v[e]]]> w[e]){
      				pre[v[e]]= e;
      				Q.push(make_pair(d[v[e]],v[e]));}}}}int main(){longlong i,j;while(scanf("%I64d%I64d",&n,&m)==2){
      		input();
      		sum =0;Dijkstra();for(i=1;i<=n;i++){
      			sum += w[pre[i]];
      			tag[pre[i]]=1;}
      		
      		printf("%I64d
      ",sum);longlong count =0;for(i=1;i<=2*m;i++)if(tag[i]){if(i > m){if(count !=0)
      		    		    printf(" %I64d",i-m);else
      		    		    printf("%I64d",i-m);}elseif(i<=m){if(count !=0)
      		    		    printf(" %I64d",i);else
      		    		    printf("%I64d",i);}
      		        count ++;}
      		printf("
      ");}return0;}

     

  • 相关阅读:
    javascript之instanceof原理
    x86之描述符表寄存器
    Mac之DTerm
    C的一些特性
    Mac i386 Operands and Addressing Modes
    shell之条件测试
    linux之dup&dup2
    javascript之this
    x86之段描述符
    进制转换
  • 原文地址:https://www.cnblogs.com/jxgapyw/p/4747732.html
Copyright © 2020-2023  润新知