题解 CF545E 【Paths and Trees】

思路:

\(\quad\)只需要以题目给定的 \(u\) 为起点跑一遍 \(Dijkstra\) 最短路即可,每次记录每个点的前驱(即到达这个点的边),注意有多个可以选择的边中选择边权最小的,感觉很像一个最小生成树,最后记得要记录树上的边权并排序再输出,起点 \(u\) 是没有前驱的,所以要从 \(2\) 开始输出。

\(\quad\)如果还不能理解就看看代码吧,有一些关键的注释。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<stack>
#include<cstring>
using namespace std;
#define re register int
#define int long long
#define LL long long
#define il inline
#define next nee
#define inf 1e18
il int read()
{
  int x=0,f=1;char ch=getchar();
  while(!isdigit(ch)&&ch!='-')ch=getchar();
  if(ch=='-')f=-1,ch=getchar();
  while(isdigit(ch))x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
  return x*f;
}
il void print(int x)
{
  if(x<0)putchar('-'),x=-x;
  if(x/10)print(x/10);
  putchar(x%10+'0');
}
const int N=3e5+5;
int n,m,next[N<<1],go[N<<1],head[N],tot,dis[N],s[N<<1],t,du[N],ans;
bool b[N];
il void Add(int x,int y,int z)
{
  next[++tot]=head[x];head[x]=tot;
  go[tot]=y;s[tot]=z;
}
struct node{
  int pos,dis;
  il bool operator<(const node &x)const
  {return dis>x.dis;}
};
priority_queue<node>q;
il void Dijkstra(int p)//板子Dijkstra
{
  for(re i=1;i<=n;i++)dis[i]=inf;dis[p]=0;
  q.push((node){p,0});
  while(!q.empty())
    {
      node tmp=q.top();q.pop();
      int x=tmp.pos;
      if(b[x])continue;
      b[x]=1;
      for(re i=head[x];i;i=next[i])
	{
	  int y=go[i];
	  if(dis[y]>dis[x]+s[i])
	    {
	      du[y]=i;//du记录前驱编号为i的边
	      dis[y]=dis[x]+s[i];
	      q.push((node){y,dis[y]});
	    }
	  else if(dis[y]==dis[x]+s[i])//有多条最短路径时
	    {if(s[du[y]]>s[i])du[y]=i;}//选择边权小的
	}
    }
}
signed main()
{
  n=read();m=read();
  for(re i=1;i<=m;i++)
    {re x=read(),y=read(),z=read();Add(x,y,z);Add(y,x,z);}
  t=read();
  Dijkstra(t);
  for(re i=1;i<=n;i++)ans+=s[du[i]];//ans统计答案
  for(re i=1;i<=n;i++)dis[i]=du[i]+1>>1;
  sort(dis+1,dis+n+1);//别忘了排序
  print(ans);putchar('\n');
  for(re i=2;i<=n;i++)print(dis[i]),putchar(' ');//从2开始输出
  return 0;
}
posted @ 2020-11-23 22:04  Farkas_W  阅读(78)  评论(0编辑  收藏  举报