A.只有1个的时候后手胜,其他先手胜
没证明,手推了前几个先手胜的看榜上过穿了就交了
#include <map> #include <set> #include <ctime> #include <cmath> #include <queue> #include <stack> #include <vector> #include <string> #include <cstdio> #include <cstdlib> #include <cstring> #include <sstream> #include <iostream> #include <algorithm> #include <functional> using namespace std; #define For(i, x, y) for(int i=x;i<=y;i++) #define _For(i, x, y) for(int i=x;i>=y;i--) #define Mem(f, x) memset(f,x,sizeof(f)) #define Sca(x) scanf("%d", &x) #define Sca2(x,y) scanf("%d%d",&x,&y) #define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z) #define Scl(x) scanf("%lld",&x); #define Pri(x) printf("%d ", x) #define Prl(x) printf("%lld ",x); #define CLR(u) for(int i=0;i<=N;i++)u[i].clear(); #define LL long long #define ULL unsigned long long #define mp make_pair #define PII pair<int,int> #define PIL pair<int,long long> #define PLL pair<long long,long long> #define pb push_back #define fi first #define se second typedef vector<int> VI; int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();} while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;} const double eps = 1e-9; const int maxn = 110; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; int N,M,K; int main(){ Sca(N); if(N == 1) puts("Yang"); else puts("Shi"); return 0; }
B.按照题意暴力递推出来,求个每一层的前缀和
pre[r] - pre[l - 1]直接计算
#include <map> #include <set> #include <ctime> #include <cmath> #include <queue> #include <stack> #include <vector> #include <string> #include <cstdio> #include <cstdlib> #include <cstring> #include <sstream> #include <iostream> #include <algorithm> #include <functional> using namespace std; #define For(i, x, y) for(int i=x;i<=y;i++) #define _For(i, x, y) for(int i=x;i>=y;i--) #define Mem(f, x) memset(f,x,sizeof(f)) #define Sca(x) scanf("%d", &x) #define Sca2(x,y) scanf("%d%d",&x,&y) #define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z) #define Scl(x) scanf("%lld",&x); #define Pri(x) printf("%d ", x) #define Prl(x) printf("%lld ",x); #define CLR(u) for(int i=0;i<=N;i++)u[i].clear(); #define LL long long #define ULL unsigned long long #define mp make_pair #define PII pair<int,int> #define PIL pair<int,long long> #define PLL pair<long long,long long> #define pb push_back #define fi first #define se second typedef vector<int> VI; int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();} while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;} const double eps = 1e-9; const int maxn = 1010; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; int N,M,K; LL MAP[maxn][maxn]; LL pre[maxn]; int main(){ Sca2(N,M); pre[1] = 1; for(int i = 2; i <= N ; i ++){ MAP[i][1] = MAP[i][i] = i; pre[i] = (2 * i + pre[i - 1]) % mod; for(int j = 2; j < i ; j ++){ MAP[i][j] = (MAP[i - 1][j] + MAP[i - 1][j - 1]) % mod; pre[i] += MAP[i][j]; pre[i] %= mod; } } while(M--){ int l,r; Sca2(l,r); Prl((pre[r] - pre[l - 1] + mod) % mod); } return 0; }
C.题目写的花里胡哨仿佛要上数据结构
看了一眼范围暴力可过
#include <map> #include <set> #include <ctime> #include <cmath> #include <queue> #include <stack> #include <vector> #include <string> #include <cstdio> #include <cstdlib> #include <cstring> #include <sstream> #include <iostream> #include <algorithm> #include <functional> using namespace std; #define For(i, x, y) for(int i=x;i<=y;i++) #define _For(i, x, y) for(int i=x;i>=y;i--) #define Mem(f, x) memset(f,x,sizeof(f)) #define Sca(x) scanf("%d", &x) #define Sca2(x,y) scanf("%d%d",&x,&y) #define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z) #define Scl(x) scanf("%lld",&x); #define Pri(x) printf("%d ", x) #define Prl(x) printf("%lld ",x); #define CLR(u) for(int i=0;i<=N;i++)u[i].clear(); #define LL long long #define ULL unsigned long long #define mp make_pair #define PII pair<int,int> #define PIL pair<int,long long> #define PLL pair<long long,long long> #define pb push_back #define fi first #define se second typedef vector<int> VI; int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();} while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;} const double eps = 1e-9; const int maxn = 1010; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; int N,M,K; int a[maxn]; int main(){ Sca2(N,M); for(int i = 1; i <= N ; i ++) Sca(a[i]); while(M--){ int x; Sca(x); int ans = 0; int cnt = 0; for(int i = 1; i <= N ; i ++){ if(x >= a[i]){ cnt = 0; continue; } if(!cnt){ cnt = 1; ans++; } } Pri(ans); } return 0; }
D.感觉尺取可以做。
但我还是离散了一下前缀和,树状数组维护比当前前缀和小的最小的位置。nlogn直接做
#include <map> #include <set> #include <ctime> #include <cmath> #include <queue> #include <stack> #include <vector> #include <string> #include <cstdio> #include <cstdlib> #include <cstring> #include <sstream> #include <iostream> #include <algorithm> #include <functional> using namespace std; #define For(i, x, y) for(int i=x;i<=y;i++) #define _For(i, x, y) for(int i=x;i>=y;i--) #define Mem(f, x) memset(f,x,sizeof(f)) #define Sca(x) scanf("%d", &x) #define Sca2(x,y) scanf("%d%d",&x,&y) #define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z) #define Scl(x) scanf("%lld",&x); #define Pri(x) printf("%d ", x) #define Prl(x) printf("%lld ",x); #define CLR(u) for(int i=0;i<=N;i++)u[i].clear(); #define LL long long #define ULL unsigned long long #define mp make_pair #define PII pair<int,int> #define PIL pair<int,long long> #define PLL pair<long long,long long> #define pb push_back #define fi first #define se second typedef vector<int> VI; int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();} while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;} const double eps = 1e-9; const int maxn = 2e6 + 1110; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; int N,M,K; int a[maxn],pre[maxn]; int Hash[maxn]; int tree[maxn]; void add(int u,int v){ for(;u <= N; u += u & -u) tree[u] = min(tree[u],v); } int getmin(int u){ int ans = INF; for(;u > 0; u -= u & -u) ans = min(ans,tree[u]); return ans; } int main(){ Sca(N); int cnt = 0; for(int i = 0 ;i <= N + 1; i ++) tree[i] = INF; for(int i = 1; i <= N ; i ++){ Sca(a[i]); pre[i] = pre[i - 1] + a[i]; Hash[++cnt] = pre[i]; } Hash[++cnt] = 0; sort(Hash + 1,Hash + 1 + cnt); cnt = unique(Hash + 1,Hash + 1 + cnt) - Hash - 1; int x = lower_bound(Hash + 1,Hash + 1 + cnt,0) - Hash; add(x,0); int ans = 0; for(int i = 1; i <= N; i ++){ pre[i] = lower_bound(Hash + 1,Hash + 1 + cnt,pre[i]) - Hash; add(pre[i],i); ans = max(ans,i - getmin(pre[i] - 1)); } Pri(ans); return 0; }
E.这个数据范围的意思就是告诉你直接BFS递推就可以了
#include <map> #include <set> #include <ctime> #include <cmath> #include <queue> #include <stack> #include <vector> #include <string> #include <cstdio> #include <cstdlib> #include <cstring> #include <sstream> #include <iostream> #include <algorithm> #include <functional> using namespace std; #define For(i, x, y) for(int i=x;i<=y;i++) #define _For(i, x, y) for(int i=x;i>=y;i--) #define Mem(f, x) memset(f,x,sizeof(f)) #define Sca(x) scanf("%d", &x) #define Sca2(x,y) scanf("%d%d",&x,&y) #define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z) #define Scl(x) scanf("%lld",&x); #define Pri(x) printf("%d ", x) #define Prl(x) printf("%lld ",x); #define CLR(u) for(int i=0;i<=N;i++)u[i].clear(); #define LL long long #define ULL unsigned long long #define mp make_pair #define PII pair<int,int> #define PIL pair<int,long long> #define PLL pair<long long,long long> #define pb push_back #define fi first #define se second typedef vector<int> VI; int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();} while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;} const double eps = 1e-9; const int maxn = 10010; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; int N,M,K; bool vis[10][10][maxn]; int MAP[10][10]; struct node{ int x,y,sum; node(){} node(int x,int y,int sum):x(x),y(y),sum(sum){} }; const int a[2][2] = {0,1,1,0}; bool check(int x,int y){ return 1 <= x && x <= N && 1 <= y &&y <= N; } int main(){ Sca(N); for(int i = 1; i <= N ; i ++){ for(int j = 1; j <= N; j ++){ Sca(MAP[i][j]); } } queue<node>Q; Q.push(node(1,1,MAP[1][1])); vis[1][1][MAP[1][1]] = 1; while(!Q.empty()){ node u = Q.front(); Q.pop(); for(int i = 0 ; i < 2; i ++){ node h = u; h.x += a[i][0]; h.y += a[i][1]; if(!check(h.x,h.y)) continue; h.sum += MAP[h.x][h.y]; if(!vis[h.x][h.y][h.sum]){ vis[h.x][h.y][h.sum] = 1; Q.push(h); } } } int ans = 0; for(int i = 0 ; i < maxn; i ++){ if(vis[N][N][i]) ans++; } Pri(ans); return 0; }
F.题目里说每个大兄弟的两个属性两两之间互不相同,这很重要
按照第一关键字从大到小排序,那么每一趟就相当于在所有大兄弟里找一个第二关键字递增的序列
暴力n ^ 2肯定不行,想办法优化就可以了,我这边先预处理nxt[i]表示下一个比这个位置的第二关键字高的位置,然后查询的时候i直接跳nxt[i]
然后并查集维护所有已经被选择过的大兄弟就可以了
#include <map> #include <set> #include <ctime> #include <cmath> #include <queue> #include <stack> #include <vector> #include <string> #include <cstdio> #include <cstdlib> #include <cstring> #include <sstream> #include <iostream> #include <algorithm> #include <functional> using namespace std; #define For(i, x, y) for(int i=x;i<=y;i++) #define _For(i, x, y) for(int i=x;i>=y;i--) #define Mem(f, x) memset(f,x,sizeof(f)) #define Sca(x) scanf("%d", &x) #define Sca2(x,y) scanf("%d%d",&x,&y) #define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z) #define Scl(x) scanf("%lld",&x) #define Pri(x) printf("%d ", x) #define Prl(x) printf("%lld ",x) #define CLR(u) for(int i=0;i<=N;i++)u[i].clear(); #define LL long long #define ULL unsigned long long #define mp make_pair #define PII pair<int,int> #define PIL pair<int,long long> #define PLL pair<long long,long long> #define pb push_back #define fi first #define se second typedef vector<int> VI; int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();} while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;} const double eps = 1e-9; const int maxn = 1e5 + 10; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; int N,M,K; struct node{ int fi,se,id; }girl[maxn]; int fa[maxn]; void init(){ for(int i = 1; i <= N + 1; i ++) fa[i] = i; } int find(int x){ return x == fa[x]?x:fa[x] = find(fa[x]); } void Union(int a,int b){ a = find(a); b = find(b); fa[a] = b; } int nxt[maxn]; int ans[maxn]; bool cmp(node a,node b){ return a.fi > b.fi; } int main(){ Sca(N); init(); for(int i = 1; i <= N ; i ++){ Sca2(girl[i].fi,girl[i].se); girl[i].id = i; } sort(girl + 1,girl + 1 + N,cmp); girl[N + 1].se = INF; for(int i = N; i >= 1; i --){ int to = i + 1; while(girl[i].se > girl[to].se){ to = nxt[to]; } nxt[i] = to; } int tot = 0; while(1){ tot++; int s = find(1); if(s == N + 1) break; int high = girl[s].se; while(s != N + 1){ Union(s,s + 1); ans[girl[s].id] = tot; high = girl[s].se; while(s != N + 1 && girl[s].se <= high) s = find(nxt[s]); } } for(int i = 1; i <= N ; i ++) Pri(ans[i]); return 0; }
G.小学数学
#include <map> #include <set> #include <ctime> #include <cmath> #include <queue> #include <stack> #include <vector> #include <string> #include <cstdio> #include <cstdlib> #include <cstring> #include <sstream> #include <iostream> #include <algorithm> #include <functional> using namespace std; #define For(i, x, y) for(int i=x;i<=y;i++) #define _For(i, x, y) for(int i=x;i>=y;i--) #define Mem(f, x) memset(f,x,sizeof(f)) #define Sca(x) scanf("%d", &x) #define Sca2(x,y) scanf("%d%d",&x,&y) #define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z) #define Scl(x) scanf("%lld",&x); #define Pri(x) printf("%d ", x) #define Prl(x) printf("%lld ",x); #define CLR(u) for(int i=0;i<=N;i++)u[i].clear(); #define LL long long #define ULL unsigned long long #define mp make_pair #define PII pair<int,int> #define PIL pair<int,long long> #define PLL pair<long long,long long> #define pb push_back #define fi first #define se second typedef vector<int> VI; int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();} while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;} const double eps = 1e-9; const int maxn = 110; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; int N,M,K; double PI = acos(-1.0); int main(){ double N; cin >> N; printf("%.3lf",N * N / (2 * PI)); return 0; }
H.
gcd(a1,a2,a3,a4 .. ,an) = gcd(a1,a2 - a1,a3 - a2,a4 - a3,....an - an - 1)
通过上面这个式子,可以把区间维护gcd变成区间维护差分序列的gcd,乍一看还是区间gcd,但是差分序列的维护就直接从区间修改降到了单点修改。
凑巧的是区间差的最大值也可以直接维护一个差分序列的最大值,再用树状数组维护一下原序列(因为上面式子右边还有一个a1,这不是差分)
这道题就解决了
#include <map> #include <set> #include <ctime> #include <cmath> #include <queue> #include <stack> #include <vector> #include <string> #include <cstdio> #include <cstdlib> #include <cstring> #include <sstream> #include <iostream> #include <algorithm> #include <functional> using namespace std; #define For(i, x, y) for(int i=x;i<=y;i++) #define _For(i, x, y) for(int i=x;i>=y;i--) #define Mem(f, x) memset(f,x,sizeof(f)) #define Sca(x) scanf("%d", &x) #define Sca2(x,y) scanf("%d%d",&x,&y) #define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z) #define Scl(x) scanf("%lld",&x) #define Pri(x) printf("%d ", x) #define Prl(x) printf("%lld ",x) #define CLR(u) for(int i=0;i<=N;i++)u[i].clear(); #define LL long long #define ULL unsigned long long #define mp make_pair #define PII pair<int,int> #define PIL pair<int,long long> #define PLL pair<long long,long long> #define pb push_back #define fi first #define se second typedef vector<int> VI; int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();} while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;} const double eps = 1e-9; const int maxn = 3e5 + 10; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; int N,M,K; LL gcd(LL a,LL b){ return b == 0?a:gcd(b,a % b); } LL a[maxn]; struct Tree{ int l,r; LL Gcd,Max,real; }tree[maxn << 2]; void Pushup(int t){ tree[t].Gcd = gcd(tree[t << 1].Gcd,tree[t << 1 | 1].Gcd); tree[t].Max = max(tree[t << 1].Max,tree[t << 1 | 1].Max); } void Build(int t,int l,int r){ tree[t].l = l; tree[t].r = r; if(l == r){ tree[t].real = a[r] - a[r - 1]; tree[t].Gcd = tree[t].Max = abs(tree[t].real); return; } int m = l + r >> 1; Build(t << 1,l,m); Build(t << 1 | 1,m + 1,r); Pushup(t); } void update(int t,int p,LL v){ if(tree[t].l == tree[t].r){ tree[t].real += v; tree[t].Gcd = tree[t].Max = abs(tree[t].real); return; } int m = tree[t].l + tree[t].r >> 1; if(p <= m) update(t << 1,p,v); else update(t << 1 | 1,p,v); Pushup(t); } LL queryMax(int t,int l,int r){ if(l <= tree[t].l && tree[t].r <= r){ return tree[t].Max; } int m = tree[t].l + tree[t].r >> 1; if(r <= m) return queryMax(t << 1,l,r); else if(l > m) return queryMax(t << 1 | 1,l,r); else{ return max(queryMax(t << 1,l,m),queryMax(t << 1 | 1,m + 1,r)); } } LL queryGcd(int t,int l,int r){ if(l <= tree[t].l && tree[t].r <= r){ return tree[t].Gcd; } int m = tree[t].l + tree[t].r >> 1; if(r <= m) return queryGcd(t << 1,l,r); else if(l > m) return queryGcd(t << 1 | 1,l,r); else{ return gcd(queryGcd(t << 1,l,m),queryGcd(t << 1 | 1,m + 1,r)); } } LL BIT[maxn]; void add(int x,LL v){ for(;x <= N + 10;x += x & -x) BIT[x] += v; } LL getsum(int x){ LL ans = 0; for(;x > 0;x -= x & -x) ans += BIT[x]; return ans; } int main(){ Sca2(N,M); for(int i = 1; i <= N ; i ++){ Scl(a[i]); add(i,a[i]); add(i + 1,-a[i]); } Build(1,2,N); while(M--){ int op,l,r; Sca3(op,l,r); if(op == 1){ LL x; Scl(x); if(l != 1) update(1,l,x); if(r != N) update(1,r + 1,-x); add(l,x); add(r + 1,-x); }else if(op == 2){ if(l == r) puts("0"); else Prl(queryMax(1,l + 1,r)); }else{ LL x = getsum(l); if(l == r) Prl(x); else Prl(gcd(x,queryGcd(1,l + 1,r))); } } return 0; }
I.数论一生黑,不会
补: 第一步前进的期望dp[1]是1 / a,(因为不会后退)
后面每一步前进的期望dp[i] = 1 (摇到前进) + b / a (摇到平局) + c / a * (dp[i - 1] + 1) (摇到后退,代价是摇了一下后退并且需要再上来)
#include <map> #include <set> #include <ctime> #include <cmath> #include <queue> #include <stack> #include <vector> #include <string> #include <cstdio> #include <cstdlib> #include <cstring> #include <sstream> #include <iostream> #include <algorithm> #include <functional> using namespace std; #define For(i, x, y) for(int i=x;i<=y;i++) #define _For(i, x, y) for(int i=x;i>=y;i--) #define Mem(f, x) memset(f,x,sizeof(f)) #define Sca(x) scanf("%d", &x) #define Sca2(x,y) scanf("%d%d",&x,&y) #define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z) #define Scl(x) scanf("%lld",&x) #define Pri(x) printf("%d ", x) #define Prl(x) printf("%lld ",x) #define CLR(u) for(int i=0;i<=N;i++)u[i].clear(); #define LL long long #define ULL unsigned long long #define mp make_pair #define PII pair<int,int> #define PIL pair<int,long long> #define PLL pair<long long,long long> #define pb push_back #define fi first #define se second typedef vector<int> VI; int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();} while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;} const double eps = 1e-9; const int maxn = 110; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; LL dp[maxn]; LL quick_power(LL a,LL b){ LL ans = 1; while(b){ if(b & 1) ans = ans * a % mod; b >>= 1; a = a * a % mod; } return ans; } LL inv(LL x){ return quick_power(x,mod - 2); } int main(){ LL n,a,b; cin >> n >> a >> b; LL ans = dp[1] = inv(a); LL c = ((1 - a - b) % mod + mod) % mod; for(int i = 2; i < n; i ++){ dp[i] = 1 + c * inv(a) % mod * (1 + dp[i - 1]) % mod + b * inv(a) % mod; dp[i] %= mod; ans = (ans + dp[i]) % mod; } Prl(ans); return 0; }
J.似乎只是个略微麻烦点的裸最短路罢了,dis[i][j]表示第i条线路第j个站点的最少花费,Dijkstra直接上就好了
#include <map> #include <set> #include <ctime> #include <cmath> #include <queue> #include <stack> #include <vector> #include <string> #include <cstdio> #include <cstdlib> #include <cstring> #include <sstream> #include <iostream> #include <algorithm> #include <functional> using namespace std; #define For(i, x, y) for(int i=x;i<=y;i++) #define _For(i, x, y) for(int i=x;i>=y;i--) #define Mem(f, x) memset(f,x,sizeof(f)) #define Sca(x) scanf("%d", &x) #define Sca2(x,y) scanf("%d%d",&x,&y) #define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z) #define Scl(x) scanf("%lld",&x) #define Pri(x) printf("%d ", x) #define Prl(x) printf("%lld ",x) #define CLR(u) for(int i=0;i<=N;i++)u[i].clear(); #define LL long long #define ULL unsigned long long #define mp make_pair #define PII pair<int,int> #define PIL pair<int,long long> #define PLL pair<long long,long long> #define pb push_back #define fi first #define se second typedef vector<int> VI; int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();} while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;} const double eps = 1e-9; const int maxn = 1010; const int maxm = 510; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; int N,M,s,t; int a[maxm],b[maxm]; int nxt[maxm][maxn],pre[maxm][maxn]; int tmp[maxn]; vector<int>P[maxn]; LL dis[maxm][maxn]; struct node{ int n,m; LL val; node(){} node(int n,int m,LL val):n(n),m(m),val(val){} friend bool operator < (node a,node b){ return a.val > b.val; } }; void Dijkstra(){ for(int i = 0 ; i <= M; i ++){ for(int j = 0 ; j <= N ; j ++) dis[i][j] = 1e18; } dis[0][s] = 0; priority_queue<node>Q; Q.push(node(s,0,0)); while(!Q.empty()){ node u = Q.top(); Q.pop(); if(dis[u.m][u.n] < u.val) continue; if(pre[u.m][u.n]){ node h = u; h.n = pre[u.m][u.n]; h.val += b[u.m]; if(dis[h.m][h.n] > h.val){ dis[h.m][h.n] = h.val; Q.push(h); } } if(nxt[u.m][u.n]){ node h = u; h.n = nxt[u.m][u.n]; h.val += b[u.m]; if(dis[h.m][h.n] > h.val){ dis[h.m][h.n] = h.val; Q.push(h); } } if(u.m){ node h = u; h.m = 0; if(dis[h.m][h.n] > h.val){ dis[h.m][h.n] = h.val; Q.push(h); } } if(!u.m){ for(int i = 0 ; i < P[u.n].size(); i ++){ int to = P[u.n][i]; node h = u; h.m = to; h.val += a[to]; if(dis[h.m][h.n] > h.val){ dis[h.m][h.n] = h.val; Q.push(h); } } } } } int main(){ scanf("%d%d%d%d",&N,&M,&s,&t); for(int i = 1; i <= M ; i ++){ int k; scanf("%d%d%d",&a[i],&b[i],&k); for(int j = 1; j <= k ; j ++){ Sca(tmp[j]); P[tmp[j]].push_back(i); nxt[i][tmp[j - 1]] = tmp[j]; pre[i][tmp[j]] = tmp[j - 1]; } } Dijkstra(); LL ans = 1e18; for(int i = 0 ; i <= M ; i ++){ ans = min(ans,dis[i][t]); } if(ans == 1e18) ans = -1; Prl(ans); return 0; }