zoukankan      html  css  js  c++  java
  • [模板]树上倍增+最大生成树

    洛谷P1967 货车运输

    题目描述

    A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路。每一条道路对车辆都有重量限制,简称限重。现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。

    输入输出格式

    输入格式:

    输入文件名为 truck.in。

    输入文件第一行有两个用一个空格隔开的整数 n,m,表示 A 国有 n 座城市和 m 条道

    路。 接下来 m 行每行 3 个整数 x、 y、 z,每两个整数之间用一个空格隔开,表示从 x 号城市到 y 号城市有一条限重为 z 的道路。注意: x 不等于 y,两座城市之间可能有多条道路 。

    接下来一行有一个整数 q,表示有 q 辆货车需要运货。

    接下来 q 行,每行两个整数 x、y,之间用一个空格隔开,表示一辆货车需要从 x 城市运输货物到 y 城市,注意: x 不等于 y 。

     

    输出格式:

    输出文件名为 truck.out。

    输出共有 q 行,每行一个整数,表示对于每一辆货车,它的最大载重是多少。如果货

    车不能到达目的地,输出-1。

     

    输入输出样例

    输入样例#1: 复制
    4 3
    1 2 4
    2 3 3
    3 1 1
    3
    1 3
    1 4
    1 3
    输出样例#1: 复制
    3
    -1
    3

    说明

    对于 30%的数据,0 < n < 1,000,0 < m < 10,000,0 < q< 1,000;

    对于 60%的数据,0 < n < 1,000,0 < m < 50,000,0 < q< 1,000;

    对于 100%的数据,0 < n < 10,000,0 < m < 50,000,0 < q< 30,000,0 ≤ z ≤ 100,000。

    解析:第一次打这种利用树上倍增求其他变量的题目,感到了顺序的可怕。。。一直是10分,发现只要交换相邻两行的位置,便100了。。。

          为防考试时出错,特此一记。

        这道题目很裸的生成树+倍增,很适合当模板打。

       但注意:   1.这题和线段树也一样坑。。。得明确更新的顺序:先更新最小值,在更新节点。

            2.记得对每棵树进行dfs/bfs。

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define rint register int 
    
    template<class T>
    inline void rd( T &x){
    	x=0;bool f=0;char ch=getchar();
        while(!isdigit(ch)) {	f=(ch==45);ch=getchar();}
        while( isdigit(ch)) {	x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
        x=f?(~x+1):x;}
    
    inline int read(){
    	int x=0;bool f=0;char ch=getchar();
    	while(!isdigit(ch)){	f=(ch==45);ch=getchar();}
    	while( isdigit(ch)){	x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    	return x=f?(~x+1):x;
    }
    
    #define man 100010
    
    int m,n,q;
    
    struct link{
    	int x,y,z;
    	link(){
    		z=0;
    	}
    }a[man<<1];
    int cmp(link x,link y){
    	return x.z>y.z;
    }
    
    int fa[man];
    
    inline int find(int x){
    	if(fa[x]!=x) fa[x]=find(fa[x]);
    	return fa[x];
    }
    
    struct edge{
    	int next,to,dis;
    }e[man<<1];
    int head[man<<1],num=0;
    
    inline void add(int from,int to,int dis){
    	e[++num].next=head[from];
    	e[num].to=to;
    	e[num].dis=dis;
    	head[from]=num;
    }
    
    int logn,dep[man];
    int minn_dis[man][30],f[man][30];
    bool vis[man];
    
    void dfs(int s,int father,int depth,int dis){
    	vis[s]=1;
    	f[s][0]=father;minn_dis[s][0]=dis;dep[s]=depth;
    	for(rint i=head[s];i;i=e[i].next){
    		int to=e[i].to;
    		if(to==father) continue;
    		dfs(to,s,depth+1,e[i].dis);
    	}
    	return ;
    }
    
    /*上述的dfs也可用以下的bfs运行*/
    inline void bfs(int s)
    {   f[s][0]=-1;dep[s]=0;vis[s]=1;
        queue<int>q;q.push(s);
        do
        {   int u=q.front();q.pop();
            for(int i=head[u];i;i=e[i].next)
            {   int to=e[i].to;
                if(!vis[to])
                {   minn_dis[to][0]=e[i].dis;
                    f[to][0]=u;
                    dep[to]=dep[u]+1;
                    q.push(to);
                    vis[to]=1;
                    }
                }
           }while(q.size());
        }
    
    inline int LCA(int x,int y)
    {   int ans=0x7fffffff;
        if(dep[x]>dep[y]) swap(x,y);
        for(int i=0;i<logn;i++)
            if(((dep[y]-dep[x])>>i)&1) ans=min(ans,minn_dis[y][i]),y=f[y][i];
        if(x==y) return ans;
        for(int i=logn;i>=0;i--)
            if(f[x][i]!=f[y][i])
            {   ans=min(ans,min(minn_dis[x][i],minn_dis[y][i]));
                x=f[x][i];y=f[y][i];
                }
        ans=min(ans,min(minn_dis[x][0],minn_dis[y][0]));
        return ans;
        }
    
    int main(){
    	memset(minn_dis,0x7f,sizeof(minn_dis));
    	n=read();m=read();
    	for(rint i=1;i<=m;i++){
    		a[i].x=read();a[i].y=read();a[i].z=max(a[i].z,read());
    	}
    	for(rint i=1;i<=n;i++) fa[i]=i;
    	sort(a+1,a+1+m,cmp);
    	int temp=0;
    	for(rint i=1;i<=m;i++){
    		int xx=find(a[i].x),yy=find(a[i].y);
    		if(xx==yy) continue;
    		fa[xx]=yy;
    		add(a[i].x,a[i].y,a[i].z);
    		add(a[i].y,a[i].x,a[i].z);
    		temp++;
    		if(temp==n-1) break; 
    	}
    	memset(vis,0,sizeof(vis));
    	for(rint i=1;i<=n;i++)
    		if(!vis[i]) dfs(i,-1,0,0);
    	logn=(int)(log(n)/log(2.0))+1;
    	for(rint j=0;j<=logn;j++)
    		for(rint i=1;i<=n;i++)
    			if(f[i][j]<0) f[i][j+1]=-1;
    			else {
    				f[i][j+1]=f[f[i][j]][j];
    				minn_dis[i][j+1]=min(minn_dis[i][j],minn_dis[f[i][j]][j]);
    			}
    	q=read();
    	for(rint i=1;i<=q;i++){
    		int x=read(),y=read();
    		if(find(x)!=find(y)) printf("-1
    ");
    		else printf("%d
    ",LCA(x,y));
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    百度和谷歌,你选择谁?
    数据库的另一种设计方法
    超级IO操作类
    WEB工具类,很强很大
    JS在AJAX中获取鼠标坐标
    弃掉HTML标记的小巧代码
    XML工具操作类,很强大
    FTP 下载功能代码
    db4o开门之篇
    ASP.NET程序中常用代码汇总(转载)
  • 原文地址:https://www.cnblogs.com/Slager-Z/p/7808881.html
Copyright © 2011-2022 走看看