zoukankan      html  css  js  c++  java
  • [20191004机房测试] ZGY的早餐

    ZGY 每天早上要从宿舍走路到机房,顺便从学校小卖部购买早饭,当然机智的 ZGY 一定会走最短路
    学校的路可以看成一无向联通张图,图上有 n 个点,m 条边,每一个点都有一个唯一的编号 1~n
    每一条边有一个边权,表示两个点之间的距离,ZGY 的宿舍在 S 点,机房在 T点,而小卖部在 H 点
    现在 ZGY 想知道从宿舍经过小卖部到达机房的最短距离
    不过因为在这个世界上有 Q个 ZGY,所以你必须回答 Q 个问题
    

    很棒的数据分治题
    读入里面说了会读入测试点编号……
    其实是很明显的暗示了……

    一半的数据保证是连通图,1 ≤ n ≤ 200,1 ≤ Q ≤ (10^5)
    这么小的n,直接Floyd跑一遍就好了,相当于Floyd的板子题

    另一半的数据保证图连通,无环,1 ≤ n ≤ (10^5),1 ≤ Q ≤ (10^5)
    联通图无环……那不就是一棵树吗!
    dfs预处理出到根节点的距离和LCA,每次询问输出就好

    代码:

    #include<bits/stdc++.h>
    #define ll long long
    #define inf 1000000000000000000
    using namespace std;
    
    int t,n,m,u,v,w;
    int q,S,H,T;
    
    struct Edge
    {
    	int next,to,dis;
    }edge[1000005];
    int cnt=0,head[100005];
    
    inline void add_edge(int from,int to,int dis)
    {
    	edge[++cnt].next=head[from];
    	edge[cnt].to=to;
    	edge[cnt].dis=dis;
    	head[from]=cnt;
    }
    
    template<class T>inline void read(T &res)
    {
    	char c;T flag=1;
    	while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
    	while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
    }
    
    ll dis[205][205];
    void Floyd()
    {
    	for(register int k=1;k<=n;++k)
    		for(register int i=1;i<=n;++i)
    			for(register int j=1;j<=n;++j)
    				dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
    }
    
    ll dep[100005];
    ll ldep[100005];
    int anc[400005][25];
    void dfs(int u,int fa)
    {
    	anc[u][0]=fa;
    	for(int i=1;i<=20;i++) anc[u][i]=anc[anc[u][i-1]][i-1];
    	for(register int i=head[u];i;i=edge[i].next)
    	{
    		int v=edge[i].to;
    		if(v==fa) continue;
    		if(dep[v]>dep[u]+edge[i].dis)
    		{
    			dep[v]=dep[u]+edge[i].dis;
    			ldep[v]=ldep[u]+1;
    			dfs(v,u);
    		}
    	}
    }
    
    int LCA(int x,int y)
    {
    	if(ldep[x]<ldep[y]) swap(x,y);
    	int deltaDep=ldep[x]-ldep[y];
    	for(int i=0;deltaDep;deltaDep>>=1,i++)
    		if(deltaDep&1) x=anc[x][i];
    	if(x==y) return x;
    	for(int i=20;anc[x][0]!=anc[y][0];i--)
    	{
    		if(anc[x][i]!=anc[y][i])
    		{
    			x=anc[x][i];
    			y=anc[y][i];
    		}
    	}
    	return anc[x][0];
    }
    
    ll Dis(int u,int v) {return dep[u]+dep[v]-2LL*dep[LCA(u,v)];}
    
    int main()
    {
    	freopen("mindis.in","r",stdin);
    	freopen("mindis.out","w",stdout);
    	read(t);read(n);read(m);
    	if(1<=t&&t<=5)
    	{
    		for(register int i=1;i<=n;++i)
    			for(register int j=1;j<=n;++j)
    				if(i!=j) dis[i][j]=inf;
    		for(register int i=1;i<=m;++i)
    		{
    			read(u);read(v);read(w);
    			dis[u][v]=dis[v][u]=w;
    		}
    		Floyd();
    		read(q);
    		while(q--)
    		{
    			read(S);read(H);read(T);
    			printf("%lld
    ",dis[S][H]+dis[H][T]);
    		}
    	}
    	else if(6<=t&&t<=10)
    	{
    		for(register int i=1;i<=m;++i)
    		{
    			read(u);read(v);read(w);
    			add_edge(u,v,w);
    			add_edge(v,u,w);
    		}
    		for(register int i=1;i<=n;++i) dep[i]=ldep[i]=inf;
    		dep[1]=0;
    		ldep[1]=1;
    		dfs(1,0);
    		read(q);
    		while(q--)
    		{
    			read(S);read(H);read(T);
    			printf("%lld
    ",Dis(S,H)+Dis(H,T));
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    mybatis中 无效的比较: invalid comparison: java.util.Date and java.lang.String
    java中日期的加减,比较,以及与String的互相转换
    Java中文件上传下载 --使用Minio
    Dubbo SPI 源码深入分析
    新建Maven项目 发布服务 注册到zookeeper
    Dubbo SPI 源码分析
    思维方法
    JDK 和 Dubbo SPI 的入门浅析Demo
    Dubbo不用注册中心实现远程调用的简单用法demo
    解决linux系统下tar解压文件报错问题
  • 原文地址:https://www.cnblogs.com/tqr06/p/11622898.html
Copyright © 2011-2022 走看看