zoukankan      html  css  js  c++  java
  • Luogu P1967 货车运输

    P1967 货车运输

    简述题意:给定一个图,求两点之间所有路径上/最短边最大的路一条路径/的最短边(突然绕 我应该表述复杂了)

    做法:最大生成树+树上倍增

    先跑一遍最大生成树。可以证明答案一定在最大生成树上。

    建树,树上跑倍增(LCA),取两点路径的(min)值就可以了w

    #include <algorithm>
    #include <iostream>
    #include <cstring> 
    #include <cstdio>
    #include <cmath>
    #define MAXN 10233
    using namespace std;
    
    
    struct qwq
    {
    	int u,v,w;
    }a[523333];
    struct qvq
    {
    	int n,t,w;
    }e[523333];
    int n,m;
    int f[MAXN];
    int q;
    int tot=0;
    struct tree
    {
    	int f,w;
    }fa[MAXN][22];
    int head[MAXN],deep[MAXN];
    bool vis[MAXN]={};
    
    
    
    bool cmp(qwq x,qwq y)
    {
    	return x.w>y.w;
    }
    int find(int x)
    {
    	if (f[x]==x) return x;
    	return f[x]=find(f[x]);
    }
    void add(int f,int t,int w)
    {
    	e[++tot].n=head[f];
    	e[tot].t=t;
    	e[tot].w=w;
    	head[f]=tot;
    }
    void kruscal()
    {
    	int sum=0;
    	for (int i=1,xx,yy;i<=m;i++)
    	{
    		xx=find(a[i].u);
    		yy=find(a[i].v);
    		if (xx!=yy)
    		{
    			sum++;
    			f[xx]=yy;
    			add(a[i].u,a[i].v,a[i].w);
    			add(a[i].v,a[i].u,a[i].w);
    		}
    		if (sum==n-1)
    		{
    			break;
    		}
    	}
    }
    void dfs(int ed)
    {
    	int t;
        vis[ed]=1;
    	for (int i=head[ed];i;i=e[i].n)
    	{
    		t=e[i].t;
    		if (vis[t]) continue;
    		deep[t]=deep[ed]+1;
    		fa[t][0].f=ed;
    		fa[t][0].w=e[i].w;
    		dfs(t);
    	}
    }
    int lca(int x,int y)
    {
    	if (find(x)!=find(y)) return -1;
    	int ans=999999999;
    	if (deep[x]>deep[y]) swap(x,y);
    	for (int i=20;i>=0;i--)
    	{
    		if (deep[fa[y][i].f]>=deep[x])
    		{
    			ans=min(ans,fa[y][i].w);
    			
    			y=fa[y][i].f;
    		}
    	}
    	if (x==y) return ans;
    	for (int i=20;i>=0;i--)
    	{
    		if (fa[x][i].f!=fa[y][i].f)
    		{
    			ans=min(ans,min(fa[x][i].w,fa[y][i].w));
    			x=fa[x][i].f; y=fa[y][i].f;
    		}
    	}
    	ans=min(ans,min(fa[x][0].w,fa[y][0].w));
    	return ans;
    }
    int main()
    {
    //	freopen("qwq.txt","w",stdout);
    	scanf("%d%d",&n,&m);
    	for (int i=1;i<=n;i++)
    	{
    		f[i]=i;
    	}
    	for (int i=1;i<=m;i++)
    	{
    		scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].w);
    	}
    	sort(a+1,a+m+1,cmp);
    	
    	kruscal();
    	for (int i=2;i<=n;i++)
    	{
    		if (!vis[i])
    		{
    			deep[i]=1;
    			dfs(i);
    			fa[i][0].f=i;
    			fa[i][0].w=999999999;
    		}
    	}
    	for (int i=1;i<=20;i++)
    	{
    		for (int j=1;j<=n;j++)
    		{
    			fa[j][i].f=fa[fa[j][i-1].f][i-1].f;
    			fa[j][i].w=min(fa[j][i-1].w, fa[fa[j][i-1].f][i-1].w);
    		}
    	}
    
    
    
    //     Debug
    //	for (int i=1;i<=tot;i++)
    //	{
    //		printf("::%d %d %d
    ",e[i].n,e[i].t,e[i].w);
    //	}
    //	printf("
    ");
    //	for (int i=1;i<=n;i++)
    //	{
    //		printf("%d ",head[i]);
    //	}
    //	printf("
    ");
    //	for (int i=1;i<=n;i++)
    //	{
    //		for (int j=1;j<=log2(n);j++)
    //		printf("%d %d ",fa[i][j].f,fa[i][j].w);
    //	}
    //	printf("
    ");
    //    for (int i=1;i<=n;i++)
    //    {
    //    	printf("
    ::%d : %d  %d
    ",i,fa[i][0].f,deep[i]);
    //	}
    //    printf("
    
    
    %d
    
    
    ",fa[1][0].f);
    
    
    
    	scanf("%d",&q);
    	for (int i=1,xx,yy;i<=q;i++)
    	{
    		scanf("%d%d",&xx,&yy);
    		printf("%d
    ",lca(xx,yy));
    	}
    	return 0;
    }
    
  • 相关阅读:
    Sqlite—修改语句(Update)
    Python—图形界面开发
    Django—模型
    Sqlite—删除语句(Delete)
    Shell—详解$( )、$(( ))、``与${ }的区别
    Shell—详解$0、$1、$2、$#、$*、$@、$?、$$变量
    排名靠前的博客
    系统架构--逻辑层
    互联网系统的通用架构笔记
    各类开源协议总结
  • 原文地址:https://www.cnblogs.com/Kan-kiz/p/10849398.html
Copyright © 2011-2022 走看看