• 「BZOJ3694」「FJ2014集训」最短路


    「BZOJ3694」「FJ2014集训」最短路

    首先树剖没得说了,这里说一下并查集的做法,

    对于一条非树边,它会影响的点就只有u(i),v(i)到lca,对于lca-v的路径上所有点x,都可通过1-t-u-v-x,长度为dep[u]+dep[v]+w(i)-dep[x],lca-u同理,

    将非树边按dep[u]+dep[v]+w(i)从小到大排序,显然每个点被前一条能更新他的边更新后即是最优解,此时将它与父亲节点合并,修改的时候用并查集向上修改即可。

     

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<queue>
    #define MP(a,b) make_pair(a,b)
    #define MAXN 1000000
    using namespace std;
    int fa[MAXN],f[MAXN][20],dep[MAXN];
    struct edge
    {
    	int u,v,w,is,nxt;
    	#define u(x)  ed[x].u
    	#define v(x)  ed[x].v
    	#define w(x)  ed[x].w
    	#define is(x) ed[x].is
    	#define n(x)  ed[x].nxt
    	friend bool operator < (edge a,edge b)
    	{
    		return a.is==b.is?(dep[a.u]+dep[a.v]+a.w)<(dep[b.u]+dep[b.v]+b.w):a.is<b.is;
    	}
    }ed[MAXN];
    int first[MAXN],num_e;
    #define f(x) first[x]
    int n,m,n0;
    inline void add_e(int u,int v,int w,int t);
    int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
    void dfs(int x,int ff,int deep)
    {
    	f[x][0]=ff;dep[x]=deep;
    	for(int i=f(x);i;i=n(i))
    	if(v(i)!=ff && is(i))
    		dfs(v(i),x,deep+w(i));
    }
    int dis[MAXN];
    signed main()
    {
    //	freopen("in.txt","r",stdin);
    
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++)fa[i]=i;
    	int ai,bi,wi,ti;
    	for(int i=1;i<=m;i++)
    	{
    		scanf("%d%d%d%d",&ai,&bi,&wi,&ti);
    		add_e(ai,bi,wi,ti),add_e(bi,ai,wi,ti);
    		if(!ti)n0+=2;
    	}
    	dfs(1,0,0);
    	for(int i=1;i<20;i++)
    		for(int j=1;j<=n;j++)
    		f[j][i]=f[f[j][i-1]][i-1];
    	sort(ed+1,ed+m*2+1);dis[1]=0;
    	for(int i=1;i<=n0;i++)
    	{
    		int x=u(i),y=v(i);
    		while(x!=y)
    		{
    			if(dep[x]<dep[y])swap(x,y);
    			if(!dis[x])dis[x]=dep[u(i)]+dep[v(i)]+w(i)-dep[x];
    			fa[x]=f[x][0];
    			x=fa[x]=find(fa[x]);
    		}
    	}
    	for(int i=2;i<=n;i++)
    		printf("%d ",!dis[i]?-1:dis[i]);
    }
    inline void add_e(int u,int v,int w,int t)
    {
    	++num_e;
    	u(num_e)=u;
    	v(num_e)=v;
    	w(num_e)=w;
    	is(num_e)=t;
    	n(num_e)=f(u);
    	f(u)=num_e;
    }
    

     

     

     

  • 相关阅读:
    关于 python 库config 的相关介绍
    关于usr/bin/ld: cannot find -lxxx问题总结
    python中argparse模块
    剑指offer——二叉树中和为某一值的路径
    剑指Offer——整数中1出现的次数(从1到n整数中1出现的次数)
    python操作redis集群
    redis-cluster配置
    redis主从同步
    redis不重启,切换RDB备份到AOF备份
    redis持久化RDB与AOF
  • 原文地址:https://www.cnblogs.com/Al-Ca/p/11182972.html
Copyright © 2020-2023  润新知