题意
有一张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;
}