2019-2020nowcoder牛客寒假基础3
本校大佬阿珂了的时候我还在模拟线段树,虽然还是在最后时间内卡进去了,基础不好呀,说明还是要不好高骛远了,见到数论就不想动不晓得是是自以为跟哪个学长学的,真想开口说自己也是一名数论选手。
A.牛牛的DRB迷宫I
简单DP,一个B点可以向下或者是向右做出贡献,其他只能一个方向,忘记取modwa+1,ce+1
#include <cstdio> #include <cmath> #include <algorithm> #include <iostream> #include <cstring> #include <queue> #include <set> #include <map> #include <stack> using namespace std; #define scd(a) scanf("%d",&a) #define scdd(a,b) scanf("%d%d",&a,&b) #define scddd(a,b,c) scanf("%d%d%d",&a,&b,&c) #define scl(a) scanf("%lld",&a) #define scll(a,b) scanf("%lld%lld",&a,&b) #define prl(a) printf("%lld\n",a) #define prd(a) printf("%d\n",a) #define prf(a) printf("%lf\n",a) #define ptd(a) printf("%d ",a) #define scf(a) scanf("%lf",&a) #define scff(a,b) scanf("%lf%lf",&a,&b) #define scfff(a,b,c) scanf("%lf%lf%lf",&a,&b,&c) #define rint register int #define mem(a) memset(a,0,sizeof(a)) #define rush() int T;scd(T);while(T--) #define lc(i) (i<<1) #define rc(i) (i<<1|1) #define mp make_pair typedef long long ll; typedef double db; inline int read() {char c=getchar();int x=0,f=1;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 int maxn = 100 + 10; const int mod = 1e9 + 7; int dp[maxn][maxn]; char s[maxn][maxn]; int main() { int n = read(),m = read(); for (int i = 1 ; i <= n; ++i) scanf("%s", s[i]+1); dp[1][1] = 1; for (int i = 1; i <= n; ++i) { for (int j = 1; j <= m; ++j) { if (s[i][j] == 'R') { dp[i][j+1] += dp[i][j]; dp[i][j+1]%=mod; } else if (s[i][j] == 'D'){ dp[i+1][j] += dp[i][j]; dp[i+1][j]%=mod; } else { dp[i][j+1] += dp[i][j];dp[i][j+1]%=mod; dp[i+1][j] += dp[i][j];dp[i+1][j]%=mod; } } } prd(dp[n][m]%mod); return 0; }
B.牛牛的DRB迷宫II
emmmm,2*2的可以把左上角的数字左移一位,把二进制数字分解,哪一位上有就建立一个通道到最右边,然后直接跑到右下角,或者是把通道建到最下面,再在最下面建一个一直往右跑的通道。
#include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <iostream> #include <string> #include <stack> #include <queue> #include <vector> #include <set> using namespace std; #define scd(a) scanf("%d",&a) #define scdd(a,b) scanf("%d%d",&a,&b) #define scddd(a,b,c) scanf("%d%d%d",&a,&b,&c) #define scl(a) scanf("%lld",&a) #define scll(a,b) scanf("%lld%lld",&a,&b) #define prl(a) printf("%lld\n",a) #define prd(a) printf("%d\n",a) #define prf(a) printf("%lf\n",a) #define ptd(a) printf("%d ",a) #define scf(a) scanf("%lf",&a) #define scff(a,b) scanf("%lf%lf",&a,&b) #define scfff(a,b,c) scanf("%lf%lf%lf",&a,&b,&c) #define rint register int #define mem(a) memset(a,0,sizeof(a)) #define rush() int T;scd(T);while(T--) #define lc(i) (i<<1) #define rc(i) (i<<1|1) #define mp make_pair #define scs(x) scanf("%s", x) typedef long long ll; typedef double db; inline int read() { char c=getchar(); int x=0,f=1; 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 int maxn = 1e2+2; const int MOD = 1e9+7; const double Pi = acos(-1.0); const double eps = 1e-6; #define mid ((l+r)>>1) char mep[maxn][maxn]; void Init(){ for (int i = 0; i < 55; ++i) { mep[i][i] = 'B'; for (int j = i + 2; j < 55; ++j) mep[j][i] = 'D'; for (int j = i + 2; j < 55; ++j) mep[i][j] = 'R'; mep[i+1][i] = 'R'; mep[i][i+1] = 'D'; } // for (int i = 0; i < 50; ++i) // { for (int j = 0; j < 50; ++j) // printf("%c ",mep[i][j]); // puts(""); // } } int main() { Init(); int n = read(); int count = 0; while (n) { if (n&1){ mep[count][count+1]='B'; } count++; n>>=1; } for (int i = 0; i < 50; ++i) mep[i][49] = 'B'; mep[49][48]='D';mep[48][48]='D'; cout<<50<<" "<<50<<endl; for (int i = 0; i < 50; ++i) { for (int j = 0; j < 50; ++j) printf("%c",mep[i][j]); puts(""); } return 0; }
C.牛牛的数组越位
不说了,模拟题一小时,晕死了
#include <cstdio> #include <cmath> #include <algorithm> #include <iostream> #include <cstring> #include <queue> #include <set> #include <map> #include <stack> using namespace std; #define scd(a) scanf("%d",&a) #define scdd(a,b) scanf("%d%d",&a,&b) #define scddd(a,b,c) scanf("%d%d%d",&a,&b,&c) #define scl(a) scanf("%lld",&a) #define scll(a,b) scanf("%lld%lld",&a,&b) #define prl(a) printf("%lld\n",a) #define prd(a) printf("%d\n",a) #define prf(a) printf("%lf\n",a) #define ptd(a) printf("%d ",a) #define scf(a) scanf("%lf",&a) #define scff(a,b) scanf("%lf%lf",&a,&b) #define scfff(a,b,c) scanf("%lf%lf%lf",&a,&b,&c) #define rint register int #define mem(a) memset(a,0,sizeof(a)) #define rush() int T;scd(T);while(T--) #define lc(i) (i<<1) #define rc(i) (i<<1|1) #define mp make_pair typedef long long ll; typedef double db; inline int read() {char c=getchar();int x=0,f=1;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 int maxn = 2e7 + 10; const int mod = 1e9 + 7; int n,m,p; int a[maxn]; int main() { rush(){ scddd(n,m,p); ll lim = n * m; for (int i = 0; i < lim; ++i) a[i] = 0; int state = 0; while (p--) { int x,y,val;scddd(x,y,val); // if(state==2)continue; int pos = x * m + y; if (x < 0 || y < 0 || x >= n || y >= m) { state = max(state,1); } if (pos < 0 || pos >= lim) { state = max(state,2); } a[pos] = val; } if (state == 2) { puts("Runtime error"); } else { int p = 0; for (int i = 0; i < n; ++i) { for (int j = 0; j < m; ++j) printf("%d ", a[p++]); puts(""); } if(state==1) puts("Undefined Behaviour"); else puts("Accepted"); } } return 0; }
D.牛牛与二叉树的数组存储
建立一颗二叉树瞎搞就好了
#include <cstdio> #include <cmath> #include <algorithm> #include <iostream> #include <cstring> #include <queue> #include <set> #include <map> #include <stack> using namespace std; #define scd(a) scanf("%d",&a) #define scdd(a,b) scanf("%d%d",&a,&b) #define scddd(a,b,c) scanf("%d%d%d",&a,&b,&c) #define scl(a) scanf("%lld",&a) #define scll(a,b) scanf("%lld%lld",&a,&b) #define prl(a) printf("%lld\n",a) #define prd(a) printf("%d\n",a) #define prf(a) printf("%lf\n",a) #define ptd(a) printf("%d ",a) #define scf(a) scanf("%lf",&a) #define scff(a,b) scanf("%lf%lf",&a,&b) #define scfff(a,b,c) scanf("%lf%lf%lf",&a,&b,&c) #define rint register int #define mem(a) memset(a,0,sizeof(a)) #define rush() int T;scd(T);while(T--) #define lc(i) (i<<1) #define rc(i) (i<<1|1) #define mp make_pair typedef long long ll; typedef double db; inline int read() {char c=getchar();int x=0,f=1;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 int maxn = 1e5 + 10; const int mod = 1e9 + 7; int a[maxn << 2]; struct node { int fa, l, r; }tree[maxn << 2]; int sz = 0;int n; void dfs(int u, int f) { if(u>n)return; if(a[u]==0)return; if(a[u]==-1)return; tree[a[u]].fa = a[f];if(tree[a[u]].fa == 0)tree[a[u]].fa = -1; tree[a[u]].l = a[lc(u)];if (tree[a[u]].l==0)tree[a[u]].l=-1; tree[a[u]].r = a[rc(u)];if (tree[a[u]].r==0)tree[a[u]].r=-1; dfs(lc(u),u); dfs(rc(u),u); } int main() { scd(n);a[0]=-1; for (int i = 1; i <= n; ++i) scd(a[i]), sz = max(sz,a[i]); dfs(1, 0); printf("The size of the tree is %d\n",sz); printf("Node %d is the root node of the tree\n", a[1]); for (int i = 1; i <= sz; ++i) { printf("The father of node %d is %d, the left child is %d, and the right child is %d\n",i,tree[i].fa,tree[i].l,tree[i].r); } return 0; }
E.牛牛的随机数
https://ac.nowcoder.com/acm/contest/3004/E
F.牛牛的Link Power I
利用前缀和的思想,每右移动一次,在当前的点插入一个1的贡献增加幅度就会增加前面的点数。
#include <cstdio> #include <cmath> #include <algorithm> #include <iostream> #include <cstring> #include <queue> #include <set> #include <map> #include <stack> using namespace std; #define scd(a) scanf("%d",&a) #define scdd(a,b) scanf("%d%d",&a,&b) #define scddd(a,b,c) scanf("%d%d%d",&a,&b,&c) #define scl(a) scanf("%lld",&a) #define scll(a,b) scanf("%lld%lld",&a,&b) #define prl(a) printf("%lld\n",a) #define prd(a) printf("%d\n",a) #define prf(a) printf("%lf\n",a) #define ptd(a) printf("%d ",a) #define scf(a) scanf("%lf",&a) #define scff(a,b) scanf("%lf%lf",&a,&b) #define scfff(a,b,c) scanf("%lf%lf%lf",&a,&b,&c) #define rint register int #define mem(a) memset(a,0,sizeof(a)) #define rush() int T;scd(T);while(T--) #define lc(i) (i<<1) #define rc(i) (i<<1|1) #define mp make_pair typedef long long ll; typedef double db; inline int read() {char c=getchar();int x=0,f=1;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 int maxn = 1e5 + 10; const ll mod = 1e9 + 7; char s[maxn]; int main() { int n = read(); cin >> s; bool st = false; ll add = 0; ll pre = 0, ans = 0; for (int i = 0; i < n; ++i) { if (!st) { if (s[i]=='1') { st = true; pre = 1; add = 0; } } else { add = (add + pre) % mod; if (s[i]=='1') { ans = (ans + add) % mod; pre++; pre %= mod; } } } prl(ans); return 0; }
G牛牛的Link Power 2
写的时间久的好处是,只用了一个函数就解决了战斗。
lsum 和 rsum 是上一题的思想,在l处或者是r处插入一个1的贡献,单点更新以后,区间合并的贡献当然包含了左右两边的1互相(瞎搞)的贡献,然后左边的点想着跑到右边瞎搞,右边的点想着去跟左边的点私会,左边每一个点可以跟右边的每一个点做出贡献,右边也是,所以对一个【(L,mid),(mid+1,R)】这种合并呢,先计算所有左边的点跑到mid的贡献,再计算所有右边的点爬到mid+1的点的贡献,这个时候他们还有一个分界线没有越过,要么是左边越过要么是右边越过,但是,就已经相当于是两个1相邻的情况了,毕竟只差一步左右两边就可以瞎搞了。
#include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <iostream> #include <string> #include <stack> #include <queue> #include <vector> #include <set> using namespace std; #define ll long long #define ull unsigned long long #define scd(a) scanf("%d",&a) #define scdd(a,b) scanf("%d%d",&a,&b) #define scddd(a,b,c) scanf("%d%d%d",&a,&b,&c) #define scl(a) scanf("%lld",&a) #define scll(a,b) scanf("%lld%lld",&a,&b) #define prl(a) printf("%lld\n",a) #define prd(a) printf("%d\n",a) #define prf(a) printf("%lf\n",a) #define ptd(a) printf("%d ",a) #define scf(a) scanf("%lf",&a) #define scff(a,b) scanf("%lf%lf",&a,&b) #define scfff(a,b,c) scanf("%lf%lf%lf",&a,&b,&c) #define rint register int #define mem(a) memset(a,0,sizeof(a)) #define rush() int T;scd(T);while(T--) #define lc(i) (i<<1) #define rc(i) (i<<1|1) #define mp make_pair #define scs(x) scanf("%s", x) const int maxn = 1e5+2; const int MOD = 1e9+7; const double Pi = acos(-1.0); const double eps = 1e-6; #define mid ((l+r)>>1) #define lson rt<<1, l, mid #define rson rt<<1|1, mid+1, r char s[maxn]; struct node{ int left, right; ll num; ll ans; ll lsum, rsum; }tree[maxn<<2]; void update(int rt, int l, int r, int p) { tree[rt].left = l; tree[rt].right = r; if (l == r) { tree[rt].num = s[l]-'0'; tree[rt].ans = 0; tree[rt].lsum = tree[rt].rsum = 0; return; } if (p <= mid) { update(lc(rt),l,mid,p); } else { update(rc(rt),mid+1,r,p); } tree[rt].num = tree[rt<<1].num + tree[rt<<1|1].num; tree[rt].lsum = ( tree[rt<<1].lsum + tree[rt<<1|1].lsum + tree[rt<<1|1].num*(tree[rt<<1|1].left-tree[rt<<1].left) )%MOD; tree[rt].rsum = ( tree[rt<<1].rsum + tree[rt<<1|1].rsum + tree[rt<<1].num*(tree[rt<<1|1].right-tree[rt<<1].right) )%MOD; tree[rt].ans = (tree[lc(rt)].ans + tree[rc(rt)].ans)%MOD + ((tree[lc(rt)].rsum + tree[lc(rt)].num)%MOD * (tree[rc(rt)].num)%MOD + tree[rc(rt)].lsum * (tree[lc(rt)].num)%MOD)%MOD; tree[rt].ans %= MOD; } int main() { int n; scd(n); scs(s+1); set<int> sat; for (int i = 1; i <= n; ++i) { update(1,1,n,i); } // for (int i = 1; i<=n<<2;++i)printf("i = %d ans=%d num=%d\n", i, tree[i].ans,tree[i].num); printf("%lld\n",tree[1].ans); int m;scd(m); for (int i = 0; i<m; ++i) { int t,ps;scdd(t,ps); if (t==1){ if (s[ps]=='0'){ s[ps]='1'; } }else{ if(s[ps]=='1'){ s[ps]='0'; } } update(1,1,n,ps); printf("%lld\n",tree[1].ans); } return 0; } /* 10 0101111001 */
H牛牛的k合因子数
埃筛多加了点东西,在筛的时候对于x是素数的情况,x的倍数的合因子包含了本身,x不是素数即为合数的时候,x是x的倍数的合因子
#include <cstdio> #include <cmath> #include <algorithm> #include <iostream> #include <cstring> #include <queue> #include <set> #include <map> #include <stack> using namespace std; #define scd(a) scanf("%d",&a) #define scdd(a,b) scanf("%d%d",&a,&b) #define scddd(a,b,c) scanf("%d%d%d",&a,&b,&c) #define scl(a) scanf("%lld",&a) #define scll(a,b) scanf("%lld%lld",&a,&b) #define prl(a) printf("%lld\n",a) #define prd(a) printf("%d\n",a) #define prf(a) printf("%lf\n",a) #define ptd(a) printf("%d ",a) #define scf(a) scanf("%lf",&a) #define scff(a,b) scanf("%lf%lf",&a,&b) #define scfff(a,b,c) scanf("%lf%lf%lf",&a,&b,&c) #define rint register int #define mem(a) memset(a,0,sizeof(a)) #define rush() int T;scd(T);while(T--) #define lc(i) (i<<1) #define rc(i) (i<<1|1) #define mp make_pair typedef long long ll; typedef double db; inline int read() {char c=getchar();int x=0,f=1;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 int maxn = 1e5 + 10; const int mod = 1e9 + 7; int isprime[maxn]; int cnt[maxn]; int main() { int n = read(),m = read(); for (int i = 2; i <= n; ++i) isprime[i] = 1; for (int i = 2; i <= n; ++i) { if (isprime[i] == 1) { for (int j = i + i; j <= n; j+=i) { isprime[j] = 0; cnt[j] = max(cnt[j], 1); } } else { for (int j = i + i; j <= n; j+=i) { cnt[j]++; } } } map<int,int>ans; for (int i = 2; i <= n; ++i) { if (ans.count(cnt[i]) == 0) { ans[cnt[i]] = 1; } else ans[cnt[i]]++; } while (m--) { int q = read(); if (ans.count(q) == 0) prd(0); else prd(ans[q]); } return 0; }
I牛牛的汉诺塔
60这个东西,显然是为了不爆掉,递归找规律
#include <cstdio> #include <cmath> #include <algorithm> #include <iostream> #include <cstring> #include <queue> #include <set> #include <map> #include <stack> using namespace std; #define scd(a) scanf("%d",&a) #define scdd(a,b) scanf("%d%d",&a,&b) #define scddd(a,b,c) scanf("%d%d%d",&a,&b,&c) #define scl(a) scanf("%lld",&a) #define scll(a,b) scanf("%lld%lld",&a,&b) #define prl(a) printf("%lld\n",a) #define prd(a) printf("%d\n",a) #define prf(a) printf("%lf\n",a) #define ptd(a) printf("%d ",a) #define scf(a) scanf("%lf",&a) #define scff(a,b) scanf("%lf%lf",&a,&b) #define scfff(a,b,c) scanf("%lf%lf%lf",&a,&b,&c) #define rint register int #define mem(a) memset(a,0,sizeof(a)) #define rush() int T;scd(T);while(T--) #define lc(i) (i<<1) #define rc(i) (i<<1|1) #define mp make_pair typedef long long ll; typedef double db; inline int read() {char c=getchar();int x=0,f=1;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 int maxn = 100 + 10; const int mod = 1e9 + 7; ll cnt[maxn][10][10]; int nn; void Hanoi(int n,int a,int b,int c) { if (n==1) { cnt[nn][a][c]++; } else{ Hanoi(n-1,a,c,b); cnt[nn][a][c]++; Hanoi(n-1,b,a,c); } } ll dp[maxn][10]; int main() { // while (1){ // } // while (1){ int n = read(); mem(dp); dp[1][2] = 1; dp[1][7] = 1; for (int i = 2; i<=n; ++i) { dp[i][7] = dp[i-1][7] * 2 + 1; dp[i][1]=dp[i][4]=dp[i-1][2]+dp[i-1][3]; dp[i][2]=dp[i-1][1]*2+1; dp[i][5]=dp[i-1][3]*2; dp[i][3]=dp[i][6]=(dp[i][7]-dp[i][1]-dp[i][2]-dp[i][4]-dp[i][5])/2; } printf("A->B:%lld\n",dp[n][1]); printf("A->C:%lld\n",dp[n][2]); printf("B->A:%lld\n",dp[n][3]); printf("B->C:%lld\n",dp[n][4]); printf("C->A:%lld\n",dp[n][5]); printf("C->B:%lld\n",dp[n][6]); printf("SUM:%lld\n",dp[n][7]); // Hanoi(nn=n,1,2,3); // int sum = 0; // for (int i=1;i<=3;++i){ // for (int j=1;j<=3;++j){ // if(i==j)continue; // sum += cnt[nn][i][j]; // printf("%c->%c:%lld\n",i+'A'-1,j+'A'-1,cnt[nn][i][j]); // } // } // prd(sum); // } return 0; }
J牛牛的宝可梦
200个点的最短路提示了到floyd为止都是非常自然的想法,抓精灵这个事情要看时间(RP)和攻击力(面板),在某一个地点抓到精灵的最优解一种做法是要对上一个地点遍历,然后我们按照时间找到时间最晚的解,把它当成是在这个地点的最优解,因为随着精灵的不断出现每一个地点的最优解都是不断更新的,所以二分查找到上一个地点最晚的时间更新即可。还有一种做法就是啥都不做,在一个地方抓到了一只精灵以后,在别的地方瞎跑抓精灵说不定比不上在这个地点等到一只满攻精灵,然后再跑过来的收获大。
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; #define mp make_pair const int maxn = 200+20; const int inf = 0x3f3f3f3f; typedef long long ll; ll dist[maxn][maxn]; struct node { int t,id; int val; } p[100010]; bool cmp(node& a,node& b) { return a.t<b.t; } vector<pair<int,int> >dp[maxn]; ll f[100010]; int main() { int n,m; scanf("%d%d",&n,&m); for (int i = 1; i <= n; ++i) { for (int j = 1; j <= n; ++j) dist[i][j] = inf; dist[i][i]=0; } for (int i = 0; i < m; ++i) { int u, v; scanf("%d%d",&u,&v); dist[u][v] = dist[v][u] = min(dist[u][v], 1ll); } for (int k = 1; k <= n; ++k) { for (int i = 1; i <= n; ++i) { for (int j = 1; j <= n; ++j) { dist[j][i] = dist[i][j] = min(dist[i][j],dist[i][k]+dist[k][j]); } } } int k; scanf("%d",&k); for (int i = 1; i <= k; ++i) { scanf("%d%d%d",&p[i].t,&p[i].id,&p[i].val); } p[0].t=p[0].val=0; p[0].id=1; sort(p+1,p+1+k,cmp); ll ans = 0; dp[1].push_back(mp(0,0)); for (int i = 1; i <= k; ++i) f[i] = -inf; f[0]=0; for (int i = 1; i <= k; ++i) { for (int j = 1; j <= n; ++j) { if(dp[j].empty()) continue; int dis=dist[j][p[i].id]; if (dis!=inf) { int id = upper_bound(dp[j].begin(), dp[j].end(), mp(p[i].t-dis, inf))-dp[j].begin()-1; if(id >= 0) { f[i]=max(f[i],f[dp[j][id].second]+p[i].val); } } } if (dp[p[i].id].empty()==false) { f[i]=max(f[i], f[dp[p[i].id].back().second]); } dp[p[i].id].push_back(mp(p[i].t, i)); ans=max(ans,f[i]); } printf("%lld\n",ans); return 0; }
另外再附加一种好像是标称,但是还是不怎么懂i-j<=200这个条件,如果说是当前这个精灵的出现的最优解肯定是由200个地点某一个地点过来的,那么最优解为什么是前200个状态来的呢。。。已经测试过把精灵的出现时间p[i].t - p[j].t <= 200,结果:wa
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; const int maxn = 200+20; const int inf = 0x3f3f3f3f; typedef long long ll; ll dist[maxn][maxn]; struct node { int t,id; ll val; }p[100010]; bool cmp(node& a,node& b){ return a.t<b.t; } ll dp[100010]; int main() { int n,m; scanf("%d%d",&n,&m); for (int i = 1; i <= n; ++i) { for (int j = 1; j <= n; ++j) dist[i][j] = inf; dist[i][i]=0; } for (int i = 0; i < m; ++i) { int u, v;scanf("%d%d",&u,&v); dist[u][v] = dist[v][u] = min(dist[u][v], 1ll); } for (int k = 1; k <= n; ++k) { for (int i = 1; i <= n; ++i) { for (int j = 1; j <= n; ++j) { dist[j][i] = dist[i][j] = min(dist[i][j],dist[i][k]+dist[k][j]); } } } int k;scanf("%d",&k); for (int i = 1; i <= k; ++i) { scanf("%d%d%lld",&p[i].t,&p[i].id,&p[i].val); } p[0].t=p[0].val=0; p[0].id=1; sort(p+1,p+1+k,cmp); ll ans = 0; for (int i = 1; i <= k; ++i) dp[i]=-1; dp[0]=0; for (int i = 0; i <= k; ++i) { for (int j = i-1; ~j&&i-j<=200; --j) { if (p[i].t-p[j].t>=dist[p[i].id][p[j].id]&&~dp[j]) dp[i]=max(dp[i],dp[j]+p[i].val); } ans=max(ans,dp[i]); } printf("%lld\n",ans); return 0; }