[10.06]T2路径子序列

题意

有一张n个点m条边的无向图,点从1到n编号,边权均为1。
定义一条从 x 1 x_1 x1 x n x_n xn 的路径 y 1 , y 2 , y 3 . . . y m y_1,y_2,y_3...y_m y1,y2,y3...ym为路径 x 1 , x 2 , x 3 . . . x n x_1, x_2 , x_3...x_n x1,x2,x3...xn 的路径子序列,当且仅当以下两条件同时满足:
1、 是一条从1到n的路径。
2、序列 y 1 , y 2 , y 3 . . . y m y_1,y_2,y_3...y_m y1,y2,y3...ym x 1 , x 2 , x 3 . . . x n x_1, x_2 , x_3...x_n x1,x2,x3...xn的一个子序列。
现在,给定一条从点1到点n的路径,你的任务就是找到该路径中点数最少的路径子序列,为了方便,你只需要输出它的长度即可。

第一行一个正整数T,表示数据组数,接下来T组数据。
每组数据第一行三个正整数n,m,k,表示图的点数、边数以及所给路径的长度。
接下来一行k+1个数,描述从点1到点n的一条路径的同时描述k条边。
接下来m-k行,每行两个正整数u,v,表示在所描述k条边外,还有一条u,v两个节点之间的双向边。

对于30%的数据,有2<=n<=15,
对于60%的数据,有2<=n<=200。
对于100%的数据,有1<=T<=100,2<=n<=50000, 1<=k<n<=m<=200000,1<=u,v<=n,每个测试点中n 的和不会超过50000,m的和不会超过200000,所描述的路径一定一条是合法的从1到n的路径,路径上的点两两不同,另外输入数据中剩下的m-k条边可能是自环,也可能是重边,且可能与任意的边重复

数据的输入有点鬼畜,我们这道题我们发现合法的路径一定是最开始给定的k个点组成的点集K中的点连成的,所以我们开一个数组记录这些点,顺便记录一下先后顺序,在后面m-k条边的时候我们只加入两个点都属于点集K的边,并且按照先后顺序建有向边,然后BFS更新一下最后输出答案就行

这道题优化能写就行,常数能小就小,数组能不清空就不清空,不然很容易T掉QAQ

#include<bits/stdc++.h>

#define MAXN 4000010
#define gtc() getchar()
#define INF 0x3f3f3f3f

using namespace std;

template<class T>

inline void read(T &s){
	T w = 1, ch = gtc(); s = 0;
	while(!isdigit(ch)){if(w == '-') w = - 1; ch = gtc();}
	while(isdigit(ch)){ s = s * 10 + ch - '0'; ch = gtc();}
	s *= w; 
}

int n, m, k, a[MAXN];
int lin[MAXN], len = 0, cnt = 0;

struct node{
	int y, ne;
}e[MAXN];

inline void add(int x, int y){
	e[++len].y = y, e[len].ne = lin[x], lin[x] = len;
}

int t;

int dis[MAXN], vis[MAXN];

queue<int> q;
void dijkstra(){
	for(int i = 1; i <= n; ++i) dis[i] = INF;
	memset(vis, 0, sizeof(vis));
	q.push(1); vis[1] = 1, dis[1] = 0;
	while(!q.empty()){
		int x = q.front(); q.pop();
		for(int i = lin[x]; i; i = e[i].ne){
			int y = e[i].y;
			if(!vis[y]){
				q.push(y), vis[y] = 1, dis[y] = dis[x] + 1;
			}
		}
	}
	printf("%d\n", dis[n]);
}

void clear(){
	memset(a, 0, sizeof(a)), cnt = 0;
	memset(lin, 0, sizeof(lin)), len = 0;
}

int main()
{
	freopen("seqpath.in", "r", stdin);
	freopen("seqpath.out", "w", stdout);
	
	read(t);
	while(t--){
		read(n), read(m), read(k);
		clear();
		int u, v; read(u); a[u] = ++cnt;
		for(int i = 1; i <= k; ++i){
			read(v); a[v] = ++cnt;
			add(u, v); u = v;
		} n = v;
		for(int i = 1; i <= m - k; ++i){
			read(u), read(v);
			if(!a[u] || !a[v]) continue;
				a[u] > a[v] ? add(v, u) : add(u, v);
		}
		dijkstra();
	}
	
	return 0;
}
reportbuilder.enterprise.for.delphi.7.v10.06 是一种用于 Delphi 7 的报告生成工具。它是 ReportBuilder 公司推出的企业级版本,具有高级报告设计和生成功能。 reportbuilder.enterprise.for.delphi.7.v10.06 可以帮助开发人员在 Delphi 7 中创建复杂、专业的报告。它提供了多种功能,如丰富的报告设计器、强大的数据源连接和报表导出选项。开发人员可以使用报告设计器轻松地设计自定义报表模板,包括表格、图表、图像和文本等元素。此外,它还支持多种数据源连接,包括数据库、Excel 和 XML 等。 reportbuilder.enterprise.for.delphi.7.v10.06 还具有灵活的报表导出功能。开发人员可以将报表导出为各种格式,如 PDF、Excel、HTML 和图像文件等。这使得用户可以方便地与他人共享报告,或在不同的应用程序和平台上使用报告。 此外,reportbuilder.enterprise.for.delphi.7.v10.06 还具有高级的报告生成功能。它支持多级数据分组、数据透视表和交叉报表等功能,使得用户可以根据自己的需求生成复杂的、具有层次结构的报告。它还提供了参数化报表、子报表和报表预览等功能,方便用户对报表进行动态调整和预览。 总之,reportbuilder.enterprise.for.delphi.7.v10.06 是一种功能强大的报告生成工具,可以帮助开发人员在 Delphi 7 中创建高级报告。它提供了丰富的报告设计和导出选项,以及灵活的报告生成功能。无论是个人开发者还是企业用户,都可以通过使用 reportbuilder.enterprise.for.delphi.7.v10.06 创建出专业、定制化的报告。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BIGBIGPPT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值