• 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;
    }
    
  • 相关阅读:
    C语言提高代码效率的几种方法
    如何写出高效率稳定的单片机代码
    位运算之 C 与或非异或
    C语言中位运算符异或“∧”的作用
    位运算之——按位与(&)操作——(快速取模算法)
    案例分析
    2018年春季个人阅读计划
    《我们应当怎样做需求分析》读书笔记
    寒假——练车、脑力风暴和辅导初中生
    需求工程:软件建模与分析 读书笔记三
  • 原文地址:https://www.cnblogs.com/cjjsb/p/9339187.html
Copyright © 2020-2023  润新知