仍是一道很簡單的基礎題,就是一個最短路徑樹的類型題目git
咱們首先能夠發現這棵樹一定知足從1出發到其它點的距離都是原圖中的最短路spa
換句話說,這棵樹上的每一條邊都是原圖從1出發到其它點的最短路上的邊code
那麼直接跑最短路,SPFA,不存在的?我只信DJ,而後記錄那些邊在最短路上get
而後直接跑MST便可。是否是很經典的水題string
而後我又莫名拿了Rank1(沒辦法天生自帶小常數)it
CODEio
#include<cstdio> #include<cctype> #include<cstring> #include<algorithm> #include<queue> using namespace std; typedef long long LL; const int N=3e5+5; struct edge { int from,to,next,v; }e[N<<1]; struct heap { int num; LL s; bool operator < (const heap a) const { return a.s<s; } }; struct data { int l,r,s; }a[N]; priority_queue <heap> small; int head[N],cnt,father[N],n,m,x,y,z,s,tot; LL dis[N]; bool vis[N]; inline char tc(void) { static char fl[100000],*A=fl,*B=fl; return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++; } inline void read(int &x) { x=0; char ch; while (!isdigit(ch=tc())); while (x=(x<<3)+(x<<1)+ch-'0',isdigit(ch=tc())); } inline void double_add(int x,int y,int z) { e[++cnt].from=x; e[cnt].to=y; e[cnt].next=head[x]; e[cnt].v=z; head[x]=cnt; e[++cnt].from=y; e[cnt].to=x; e[cnt].next=head[y]; e[cnt].v=z; head[y]=cnt; } inline bool cmp(data a,data b) { return a.s<b.s; } inline int getfather(int k) { return father[k]^k?father[k]=getfather(father[k]):k; } inline LL MST(void) { register int i; LL ans=0; sort(a+1,a+tot+1,cmp); for (i=1;i<=n;++i) father[i]=i; for (i=1;i<=tot;++i) { int fx=getfather(a[i].l),fy=getfather(a[i].r); if (!vis[a[i].r]&&fx!=fy) father[fx]=fy,ans+=a[i].s,vis[a[i].r]=1; } return ans; } int main() { //freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout); int i; read(n); read(m); memset(head,-1,sizeof(head)); memset(e,-1,sizeof(e)); for (i=1;i<=m;++i) read(x),read(y),read(z),double_add(x,y,z); memset(dis,63,sizeof(dis)); read(s); dis[s]=0; small.push((heap){s,0}); while (!small.empty()) { int now=small.top().num; small.pop(); if (vis[now]) continue; vis[now]=1; for (i=head[now];i!=-1;i=e[i].next) if (dis[e[i].to]>dis[now]+1LL*e[i].v) { dis[e[i].to]=dis[now]+1LL*e[i].v; small.push((heap){e[i].to,dis[e[i].to]}); } } memset(vis,0,sizeof(vis)); for (i=1;i<=cnt;++i) if (dis[e[i].from]+1LL*e[i].v==dis[e[i].to]) a[++tot]=(data){e[i].from,e[i].to,e[i].v}; return printf("%lld",MST()),0; }