• 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;}

     

  • 相关阅读:
    零基础学习接口测试-接口文档
    零基础学习接口测试-HTTP消息结构
    零基础学习接口测试—HTTP协议基础知识
    零基础学习接口测试-接口测试基础知识
    MySQL数据库安装
    软件测试基础-软件测试基本流程
    零基础学习接口测试-HTTPS协议
    软件测试基础-软件测试分类
    BLE5.2 CIS Data Flush Point点SN和NESN变化机制探讨
    使用Jlink给CC2640R2F烧写固件方法
  • 原文地址:https://www.cnblogs.com/jxgapyw/p/4747732.html
Copyright © 2020-2023  润新知