51Nod 1443 路径和树

还是一道很简单的基础题,就是一个最短路径树的类型题目

我们首先可以发现这棵树必定满足从1出发到其它点的距离都是原图中的最短路

换句话说,这棵树上的每一条边都是原图从1出发到其它点的最短路上的边

那么直接跑最短路,SPFA,不存在的?我只信DJ,然后记录那些边在最短路上

然后直接跑MST即可。是不是很经典的水题

然后我又莫名拿了Rank1(没办法天生自带小常数

CODE

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

猜你喜欢

转载自www.cnblogs.com/cjjsb/p/9339187.html
今日推荐