题意:交互题,给定一个简单无向图和$A,B(1\leq A\lt B)$,你可以对每条边指定其边权为$A$或$B$后通过交互库询问$S\rightarrow T$的最短路($S,T$在程序运行之前已经确定),但你不知道$S,T$,现在要求$S$和$T$

无论是什么做法,我们首先需要知道边权为$1$时的最短路$dis$,在开始时把所有边设为$A$,调用一次即可

从部分分入手,第一个部分分(subtask1,2):图是一棵树,已知根是$S$,求$T$

因为只能调用很少次交互库,所以考虑二分

我们在bfs序上二分,假设当前二分到$[l,r]$,我们要检查$T$的bfs序是否在$[l,mid]$中,如果我们将bfs序在$[1,mid]$中的点的祖先边全部设为$A$,将其他边设为$B$,并且此时最短路为$dis\cdot A$,那么显然$T$的bfs序在$[l,mid]$中(因为任何bfs序在$[mid+1,r]$中的节点到根至少经过一条$B$边),于是时间复杂度为$O(n\log n)$,调用次数为$1+\left\lceil\log_2n\right\rceil$

然后是第二个部分分(subtask3,4):图是一棵树

如果我们能找出一条在$S\rightarrow T$最短路上的边,那么删掉这条边后对两棵树套用上面的算法即可

要找到任意一条这样的边,还是得二分,二分边的编号,二分到$[l,r]$时把$[1,mid]$的边设为$B$,把$[mid+1,n-1]$的边设为$A$,如果最短路没有变化,那么这条边在$[mid+1,r]$,否则在$[l,mid]$,于是时间复杂度为$O(n\log_2n)$,调用次数为$1+\left\lceil\log_2n\right\rceil+2\left\lceil\log_2\frac n2\right\rceil$

然后是一般情况(subtask5,6)

我们同样想找到一条在$S\rightarrow T$的任意一条最短路上的边,还是得二分边的编号,一开始把所有边设为$A$,二分到$[l,r]$时先把$[l,mid]$设为$B$,查询最短路,如果最短路变化了,那么$[l,mid]$中一定有这样的边,于是先把$[l,mid]$设回$A$,再去$[l,mid]$中寻找答案,否则它就在$[mid+1,r]$了

假设我们找出来的边是$(x,y)$,我们用这条边构造两个不相交的集合$S_1,S_2$(以下的距离都是边权为$1$的距离)

如果一个点$u$满足$dis_{u,x}<dis_{u,y}$,那么$u\in S_1$,如果$u$满足$dis_{u,x}\gt dis_{u,y}$,那么$u\in S_2$

在$S_1$中以$x$为根构造bfs树,在$S_2$中以$y$为根构造bfs树,那么$S\rightarrow T$一定存在一条最短路是只经过树边和$(x,y)$的

将非树边设为$B$,将树边和$(x,y)$设为$A$,那么接下来要做的事情就和第二个部分分的最后一步一样了

总时间复杂度$O\left(m(\log m+\log n)\right)$,调用次数为$1+\left\lceil\log_2m\right\rceil+2\left\lceil\log_2\frac n2\right\rceil$,刚好是$50$,但官方数据好像并没有卡满...

神仙图论题...

#include"highway.h"
#include<vector>
#include<algorithm>
#include<string.h>
using namespace std;
typedef long long ll;
const int inf=2147483647;
int abs(int x){return x>0?x:-x;}
int h[90010],nex[260010],to[260010],id[260010],M,n,m;
void add(int a,int b,int c){
	M++;
	to[M]=b;
	id[M]=c;
	nex[M]=h[a];
	h[a]=M;
}
int q[90010],d1[90010],d2[90010];
void getdis(int*d,int x){
	int head,tail,i;
	for(i=1;i<=n;i++)d[i]=inf;
	head=tail=1;
	q[1]=x;
	d[x]=0;
	while(head<=tail){
		x=q[head++];
		for(i=h[x];i;i=nex[i]){
			if(d[x]+1<d[to[i]]){
				d[to[i]]=d[x]+1;
				q[++tail]=to[i];
			}
		}
	}
}
vector<int>u,v,w;
int fa[90010],bfn[90010];
bool t1[260010],t2[260010];
void bfs(int x,bool*t){
	int head,tail,i;
	head=tail=1;
	q[1]=x;
	M=0;
	while(head<=tail){
		x=q[head++];
		bfn[x]=++M;
		for(i=h[x];i;i=nex[i]){
			if(to[i]!=fa[x]&&t[i]){
				fa[to[i]]=x;
				q[++tail]=to[i];
			}
		}
	}
}
ll dis;
int solve(int x,int y,bool*t){
	memset(fa,0,sizeof(fa));
	memset(bfn,0,sizeof(bfn));
	int l,r,mid,ans,i;
	fa[y]=x;
	bfs(y,t);
	l=1;
	r=M;
	ans=0;
	while(l<=r){
		mid=(l+r)>>1;
		for(i=0;i<m;i++){
			x=u[i];
			y=v[i];
			if(!t1[i*2+1]&&!t2[i*2+1])
				w[i]=1;
			else if(!t[i*2+1])
				w[i]=0;
			else{
				if(fa[x]==y)swap(x,y);
				w[i]=bfn[y]>mid;
			}
		}
		if(ask(w)==dis){
			ans=mid;
			r=mid-1;
		}else
			l=mid+1;
	}
	for(i=1;i<=n;i++){
		if(bfn[i]==ans)break;
	}
	return i;
}
int sfa[90010];
int get(int x){return x==sfa[x]?x:(sfa[x]=get(sfa[x]));}
void buildt1(int x){
	int head,tail,i;
	for(i=1;i<=n;i++)sfa[i]=i;
	head=tail=1;
	q[1]=x;
	while(head<=tail){
		x=q[head++];
		for(i=h[x];i;i=nex[i]){
			if(d1[x]<d2[x]&&d1[to[i]]<d2[to[i]]&&d1[x]!=d1[to[i]]&&get(x)!=get(to[i])){
				t1[i]=t1[((i-1)^1)+1]=1;
				sfa[get(to[i])]=get(x);
				q[++tail]=to[i];
			}
		}
	}
}
void buildt2(int x){
	int head,tail,i;
	for(i=1;i<=n;i++)sfa[i]=i;
	head=tail=1;
	q[1]=x;
	while(head<=tail){
		x=q[head++];
		for(i=h[x];i;i=nex[i]){
			if(d1[x]>d2[x]&&d1[to[i]]>d2[to[i]]&&d2[x]!=d2[to[i]]&&get(x)!=get(to[i])){
				t2[i]=t2[((i-1)^1)+1]=1;
				sfa[get(to[i])]=get(x);
				q[++tail]=to[i];
			}
		}
	}
}
void find_pair(int n,vector<int>u,vector<int>v,int A,int B){
	int i,x,y,l,r,mid;
	m=u.size();
	w.resize(m);
	for(i=0;i<m;i++){
		u[i]++;
		v[i]++;
		add(u[i],v[i],i);
		add(v[i],u[i],i);
	}
	::n=n;
	::u=u;
	::v=v;
	for(i=0;i<m;i++)w[i]=0;
	dis=ask(w);
	l=0;
	r=m-1;
	while(l<r){
		mid=(l+r)>>1;
		for(i=l;i<=mid;i++)w[i]=1;
		if(ask(w)!=dis){
			for(i=l;i<=mid;i++)w[i]=0;
			r=mid;
		}else
			l=mid+1;
	}
	x=u[l];
	y=v[l];
	getdis(d1,x);
	getdis(d2,y);
	buildt1(x);
	buildt2(y);
	t1[l*2+1]=t1[l*2+2]=t2[l*2+1]=t2[l*2+2]=1;
	answer(solve(x,y,t2)-1,solve(y,x,t1)-1);
}

[UOJ409]Highway Tolls的更多相关文章

  1. zoj 3946 Highway Project(最短路 + 优先队列)

    Highway Project Time Limit: 2 Seconds      Memory Limit: 65536 KB Edward, the emperor of the Marjar ...

  2. [HihoCoder] Highway 高速公路问题

    Description In the city, there is a one-way straight highway starts from the northern end, traverses ...

  3. Total Highway Distance

    Total Highway Distance 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 Little Hi and Little Ho are playing a ...

  4. 基于pytorch实现HighWay Networks之Train Deep Networks

    (一)Highway Networks 与 Deep Networks 的关系 理论实践表明神经网络的深度是至关重要的,深层神经网络在很多方面都已经取得了很好的效果,例如,在1000-class Im ...

  5. Highway Networks

    一 .Highway Networks 与 Deep Networks 的关系 深层神经网络相比于浅层神经网络具有更好的效果,在很多方面都已经取得了很好的效果,特别是在图像处理方面已经取得了很大的突破 ...

  6. Highway Networks Pytorch

    导读 本文讨论了深层神经网络训练困难的原因以及如何使用Highway Networks去解决深层神经网络训练的困难,并且在pytorch上实现了Highway Networks. 一 .Highway ...

  7. Highway LSTM 学习笔记

    Highway LSTM 学习笔记 zoerywzhou@gmail.com http://www.cnblogs.com/swje/ 作者:Zhouwan  2016-4-5   声明 1)该Dee ...

  8. ZOJ3946:Highway Project(最短路变形)

    本文转载自:http://www.javaxxz.com/thread-359442-1-1.html Edward, the emperor of the Marjar Empire, wants ...

  9. 基于pytorch实现HighWay Networks之Highway Networks详解

    (一)简述---承接上文---基于pytorch实现HighWay Networks之Train Deep Networks 上文已经介绍过Highway Netwotrks提出的目的就是解决深层神经 ...

随机推荐

  1. Edgware Feign hystrix-dashboard

    相关依赖 <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring ...

  2. 细数雷军系成员,27家公司3家IPO

    自 2004 年至今,作为天使投资人和顺为基金创始合伙人,雷军共投了移动互联网.电子商务.互联网社区等领域内的 27 家创业公司,其中欢聚时代.猎豹移动.迅雷三家公司成功上市.小米科技虽然还未 IPO ...

  3. Linux线程基础函数

    1. 线程标识: (1) 比较两个线程ID: #include <pthread.h> int pthread_equal(pthread_t tid1, pthread_t tid2); ...

  4. Linux 入门记录:五、vi、vim 编辑器

    一.vi.vim编辑器 vi 是一个命令行界面下的文本编辑工具,最早在 1976 年由 Bill Joy 开发.当时名字叫做 ex.vi 支持绝大多数操作系统(最早在类 Unix 操作系统的 BSD上 ...

  5. pillow模块的学习

    https://github.com/wangbinyq/pillow_example http://pillow.readthedocs.org/en/latest/handbook/tutoria ...

  6. mac系统中实现vitualBox中访问内网端口

    第一步,增加外网网段 打开vitualbox后,按管理菜单,点击->主机网络管理器,如图1所示.点击创建,创建下个网络主机. 图1 然后,关掉虚拟机,虚拟机的设置中,找到网络选项卡,然后点击网络 ...

  7. pycaffe使用.solverstate文件继续训练

    import caffe solver_file = "solver.prototxt" solverstate = "xx.solverstate" caff ...

  8. python一步高级编程

    1.==,is的使用 总结 ·is是比较两个引用是否指向了同一个对象(引用比较). ·==是比较两个对象是否相等. 2.深拷贝.浅拷贝 1.浅拷贝 浅拷贝是对于一个对象的顶层拷贝 通俗的理解是:拷贝了 ...

  9. C语言比较巧妙的字符串分割程序

    在解析字符串时,能够解析的给出每个字符串的长度.内容.以及每个字符串的第一个字符的地址. short i; ; //切割之后的字符串的个数 ,ItemLen[],Idx[], ThCommandLen ...

  10. tinyhttpd ------ C 语言实现最简单的 HTTP 服务器

    工作流程: 1>服务器启动,在指定端口或随机选取端口绑定httpd服务. 2>收到一个http请求时(其实就是listen端口accept的时候),派生一个线程运行accept_reque ...