2018年10月24日提高组 T3 TRAVEL

news/2024/7/16 7:23:37

大意

给定每个点之间连接道路的限制 l , r l,r l,r,求出从1到 n n n可以带走最大的区间,如果有多组解,输出字典序最小的一组


思路

首先很容易想到 d f s dfs dfs

#include<algorithm>
#include<vector>
#include<cstdio>
#define ri register int
using namespace std;int n,m,head[1001],tot,x,y,l,r,ansl,ansr;
struct node{int p,l,r;};
vector<node>e[6001];
bool vis[1001];
inline void dfs(ri x,ri L,ri R)//计算所有从1到n的路,求答案
{
	if(R-L<ansr-ansl||(R-L==ansr-ansl&&L>=ansl)) return;//最优化剪枝
	if(x==n)
	{
		if(R-L>ansr-ansl||R-L==ansr-ansl&&L<ansl)
		{
			ansl=L;
			ansr=R;
		}
		return;
	}
	for(ri i=0;i<e[x].size();i++)
	{
		int y=e[x][i].p,xl=e[x][i].l,xr=e[x][i].r;
		if(!vis[y]) {vis[y]=true;dfs(y,max(xl,L),min(xr,R));vis[y]=false;}
	}
	return;
}
signed main()
{
	scanf("%d%d",&n,&m);
	for(ri i=1;i<=m;i++)
	{
		scanf("%d%d%d%d",&x,&y,&l,&r);
		e[x].push_back((node){y,l,r});
		e[y].push_back((node){x,l,r});
	}
	vis[1]=true;dfs(1,1,1000000);
	printf("%d\n",ansr-ansl+1);
	for(ri i=ansl;i<=ansr;i++) printf("%d ",i);
}

于是愉快的 T l e Tle Tle

我们想到了一种固定边界的方法,假设我们枚举左边界,然后二分右边界,然后用一种算法判断是否可行(本人用的是并查集),但是这样的复杂度是 O ( 1 0 6 l o g 1 0 12 ) O(10^6log10^{12}) O(106log1012) T l e Tle Tle

然后我们发现左右边界永远都是所有路中的,于是我们可以只枚举出现的左右边界,复杂度为 O ( m 2 ) O(m^2) O(m2)可以过


代码

#include<cstdio>
#include<algorithm>
#define ri register int
using namespace std;int f[1001],n,m,ans,ansl,l,r;
struct node{int l,r,u,v;}a[3001];
inline int find(ri x){return x==f[x]?x:f[x]=find(f[x]);}//并查集
inline bool cmp(node x,node y){return x.r<y.r;}//排序
inline void check(ri x)//判断是否可以到达
{
	for(ri i=1;i<=n;i++) f[i]=i;
	for(ri i=m;i>0;i--)
	{
		if(a[i].l>x) continue;//超出了我枚举的限制,就不走了
		int u=find(a[i].u),v=find(a[i].v);
		if(u!=v) f[u]=v;
		if(find(1)==find(n))//可以到达
		{
			r=a[i].r;return;//因为我的r是排了序的,所以前面搜到的一定是最优的
		}
	}
	r=-1000000000;return;//没找到
}
signed main()
{
	scanf("%d%d",&n,&m);
	for(ri i=1;i<=m;i++) scanf("%d%d%d%d",&a[i].u,&a[i].v,&a[i].l,&a[i].r);
	sort(a+1,a+1+m,cmp);//排序
	for(ri i=1;i<=m;i++)
	{
		l=a[i].l;
		check(l);
		if(r-l+1>ans||r-l+1==ans&&l<ansl)//比较
		{
			ans=r-l+1;
			ansl=l;
		}
	}
	printf("%d\n",ans);
	for(ri i=ansl;i<ansl+ans;i++) printf("%d ",i);//输出
}

http://www.niftyadmin.cn/n/2679851.html

相关文章

Oracle PL/SQL 程序设计读书笔记 - 第15章 数据提取

Oracle PL/SQL 程序设计读书笔记 - 第15章 数据提取 Oracle PL/SQL 程序设计读书笔记 - 第15章 数据提取 每当在PL/SQL中执行一个SQL语句时&#xff0c;Oracle数据库都会为这个语句分配一个私有工作区&#xff0c;并在系统全局区&#xff08;SGA&#xff09;中管理该SQL语句指…

如何在jsp页面中引入css样式表文件和javascript文件

一&#xff1a;如何在jsp页面中引入css样式表文件? 1&#xff0c; 首先把写好的css样式表内容存为*.css格式。如style.css 2&#xff0c; 在页面中引入这个css 样式文件。用如下的方式引入。 <link rel"stylesheet" href"./css/style.css" type&qu…

七夕节(打表水题)

七夕节 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 5086 Accepted Submission(s): 1785 Problem Description七夕节那天,月老来到数字王国,他在城门上贴了一张告示,并且和数字王国的人们说:"你们想知道你们…

2018年10月24日提高组模拟赛Week 6总结

第一题数论基础&#xff0c;第二题打了暴力&#xff0c;第三题也暴力&#xff0c;于是水了Rank3Rank3Rank3&#xff0c;不得不膜拜ssl_wycssl\_wycssl_wyc巨老200 T1 码灵鼠 https://blog.csdn.net/xuxiayang/article/details/83419505 占比方法0~100各种蒙分100数论基础T2 S…

通过程序一句话备份恢复SqlServer数据库

通过程序一句话备份恢复SqlServer数据库 备份语句&#xff1a;BACKUP DATABASE[__DataBaseName__] TO DISK N//LocalCoputerNameOrIP/ShareDocument/FileName.bat WITH INIT, NOUNLOAD,NOSKIP,STATS10, NOFORMAT 恢复语句&#xff1a;Restore DataBase[__DataBaseName__] fro…

c语言求一元二次方程的根_C语言程序的测试

C语言程序的测试系统提供的图片程序调试的任务是排除程序中的错误&#xff0c;使程序能顺利地运行并得到预期的效果。程序的调试阶段不仅要发现和消除语法上的错误&#xff0c;还要发现和消除逻辑错误和运行错误。除了可以利用编译时提示的“出错信息”来发现和改正语法错误外&…

触发器执行顺序----From Me

创建新纪录&#xff1a; when-create-record when-new-block-instance when-new-record-instance转载于:https://www.cnblogs.com/CiWEi-/archive/2011/12/19/2293500.html

Linux shell命令 cp 加上-f还是提示是否覆盖

这是由于环境变量中有 allias cpcp -i 为了去掉这个系统自带的别名&#xff0c;能够使用grep -r --include"*" "alias cp" /查找设置这个环境变量的脚本文件&#xff1a; 我的ubuntu机器上是&#xff1a; ./.bash_aliases:alias cpcp -i 于是我将./.bash_…