8.20 usaco
summary:14
1.k短路
2.tarjan缩无向图点
3.复习了SA
4.差分约束
5.求第二短路
洛谷3824:dfs优化背包。开始的时候mle了,然后我就把a[i],w[i]去掉。。。。就A了。优化空间。。。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define clr(x,c) memset(x,c,sizeof(x)) int read(){ int x=0;char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) x=x*10+c-'0',c=getchar(); return x; } const int nmax=10000005; int sum[nmax],cnt[nmax],ans=0,n,m; void maxs(int &a,int b){ if(a<b) a=b; } void dfs(int cur,int x,int y){ if(sum[cur-1]+x<=m) { maxs(ans,cnt[cur-1]+y);return ; } maxs(ans,y); dwn(i,cur-1,1){ if(x+sum[i]-sum[i-1]<=m) dfs(i,x+sum[i]-sum[i-1],y+cnt[i]-cnt[i-1]); } } int main(){ m=read(),n=read();int u,v; rep(i,1,n) u=read(),v=read(),sum[i]=sum[i-1]+u,cnt[i]=cnt[i-1]+v; dfs(n+1,0,0); printf("%d\n",ans); return 0; }
bzoj1734:裸二分答案。。。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define clr(x,c) memset(x,c,sizeof(x)) int read(){ int x=0;char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) x=x*10+c-'0',c=getchar(); return x; } const int nmax=1e5+5; int a[nmax],n,c; bool check(int x){ int sum=1,pre=a[1]; rep(i,2,n) { if(a[i]-pre>=x) sum++,pre=a[i]; } return sum>=c; } int main(){ n=read(),c=read(); rep(i,1,n) a[i]=read(); sort(a+1,a+n+1); int l=0,r=a[n],mid,ans=0; while(l<=r){ mid=(l+r)>>1; if(check(mid)) ans=mid,l=mid+1; else r=mid-1; } printf("%d\n",ans); return 0; }
bzoj1733:二分答案+最大流就可以了。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define clr(x,c) memset(x,c,sizeof(x)) #define qwq(x) for(edge *o=head[x];o;o=o->next) int read(){ int x=0;char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) x=x*10+c-'0',c=getchar(); return x; } const int nmax=205; const int maxn=160005; const int inf=0x7f7f7f7f; struct edge{ int to,cap,dist,p;edge *next,*rev; }; edge es[maxn],*pt=es,*head[nmax],*p[nmax],*cur[nmax]; void add(int u,int v,int d){ pt->to=v;pt->dist=d;pt->cap=pt->p=1;pt->next=head[u];head[u]=pt++; pt->to=u;pt->dist=d;pt->cap=pt->p=0;pt->next=head[v];head[v]=pt++; head[u]->rev=head[v];head[v]->rev=head[u]; } int n,m,T,cnt[nmax],h[nmax]; void mins(int &a,int b){ if(a>b) a=b; } int maxflow(){ clr(cnt,0),cnt[0]=n;clr(h,0); int flow=0,a=inf,x=1;edge *e; while(h[1]<n){ for(e=cur[x];e;e=e->next) if(e->cap>0&&h[e->to]==h[x]-1) break; if(e){ mins(a,e->cap),p[e->to]=cur[x]=e;x=e->to; if(x==n){ while(x!=1) p[x]->cap-=a,p[x]->rev->cap+=a,x=p[x]->rev->to; flow+=a,a=inf; } }else{ if(!--cnt[h[x]]) break; h[x]=n; for(e=head[x];e;e=e->next) if(e->cap>0&&h[x]>h[e->to]+1) h[x]=h[e->to]+1,cur[x]=e; cnt[h[x]]++; if(x!=1) x=p[x]->rev->to; } } return flow; } bool check(int x){ rep(i,1,n) qwq(i) { if(o->dist<=x) o->cap=o->p; else o->cap=0; } return maxflow()>=T; } void maxs(int &a,int b){ if(a<b) a=b; } int main(){ n=read(),m=read(),T=read();int u,v,d,l=0,r=0; rep(i,1,m) u=read(),v=read(),d=read(),add(u,v,d),add(v,u,d),maxs(r,d); int ans=0,mid; while(l<=r){ mid=(l+r)>>1; if(check(mid)) ans=mid,r=mid-1; else l=mid+1; } printf("%d\n",ans); return 0; }
bzoj1731:差分约束。s[j]-s[i]<=k/s[j]-s[i]>=k=>s[i]-s[j]<=-k/s[i]-s[i-1]>=0=>s[i-1]-s[i]<=0
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<queue> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define clr(x,c) memset(x,c,sizeof(x)) #define qwq(x) for(edge *o=head[x];o;o=o->next) #define ll long long int read(){ int x=0;char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) x=x*10+c-'0',c=getchar(); return x; } const int nmax=1005; const int maxn=30005; const ll inf=1e15; struct edge{ int to,dist;edge *next; }; edge es[maxn],*pt=es,*head[nmax]; void add(int u,int v,int d){ pt->to=v;pt->dist=d;pt->next=head[u];head[u]=pt++; } queue<int>q; ll dist[nmax];int cnt[nmax];bool inq[nmax]; bool spfa(int n){ rep(i,2,n) dist[i]=inf;dist[1]=0; clr(inq,0),clr(cnt,0);inq[1]=1,cnt[1]=1; q.push(1); while(!q.empty()){ int x=q.front();q.pop();inq[x]=0; qwq(x) if(dist[o->to]>dist[x]+o->dist){ dist[o->to]=dist[x]+o->dist; if(!inq[o->to]){ if(++cnt[o->to]==n) return false; q.push(o->to);inq[o->to]=1; } } } } int main(){ int n=read(),ml=read(),md=read(),u,v,d; rep(i,1,ml) u=read(),v=read(),d=read(),add(u,v,d); rep(i,1,md) u=read(),v=read(),d=read(),add(v,u,-d); rep(i,2,n) add(i,i-1,0); if(spfa(n)) { if(dist[n]==inf) printf("-2\n"); else printf("%lld\n",dist[n]); }else printf("-1\n"); return 0; }
bzoj1726:求第二短路。我的写法不知道为什么WA了。。网上的题解也没人和我写的一样。。。
my code:
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<queue> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define clr(x,c) memset(x,c,sizeof(x)) #define qwq(x) for(edge *o=head[x];o;o=o->next) int read(){ int x=0;char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) x=x*10+c-'0',c=getchar(); return x; } const int nmax=5005; const int maxn=2000005; const int inf=0x7f7f7f7f; struct edge{ int to,dist;edge *next; }; edge es[maxn],*pt=es,*head[nmax]; void add(int u,int v,int d){ pt->to=v;pt->dist=d;pt->next=head[u];head[u]=pt++; pt->to=u;pt->dist=d;pt->next=head[v];head[v]=pt++; } struct node{ int x,dist; node(int x,int dist):x(x),dist(dist){}; node(){}; bool operator<(const node&rhs)const{ return dist>rhs.dist;} }; priority_queue<node>q; int da[nmax],db[nmax]; void dijkstra(){ clr(da,0x7f);clr(db,0x7f);da[1]=0;db[1]=0;q.push(node(1,0)); int tx,td; while(!q.empty()){ node oo=q.top();q.pop(); tx=oo.x,td=oo.dist; if(td!=da[tx]&&td!=db[tx]) continue; qwq(tx) { if(da[o->to]>td+o->dist){ db[o->to]=da[o->to]; da[o->to]=td+o->dist; q.push(node(o->to,da[o->to])); }else if(db[o->to]>td+o->dist){ db[o->to]=td+o->dist; q.push(node(o->to,db[o->to])); } } } } int main(){ int n=read(),m=read(),u,v,d; rep(i,1,m) u=read(),v=read(),d=read(),add(u,v,d); dijkstra(); printf("%d\n",db[n]); return 0; }
ac code:
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<queue> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define clr(x,c) memset(x,c,sizeof(x)) #define qwq(x) for(edge *o=head[x];o;o=o->next) int read(){ int x=0;char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) x=x*10+c-'0',c=getchar(); return x; } const int nmax=5005; const int maxn=2000005; const int inf=0x7f7f7f7f; struct edge{ int to,dist;edge *next; }; edge es[maxn],*pt=es,*head[nmax]; void add(int u,int v,int d){ pt->to=v;pt->dist=d;pt->next=head[u];head[u]=pt++; pt->to=u;pt->dist=d;pt->next=head[v];head[v]=pt++; } struct node{ int x,dist; node(int x,int dist):x(x),dist(dist){}; node(){}; bool operator<(const node&rhs)const{ return dist>rhs.dist;} }; priority_queue<node>q; int da[nmax],db[nmax]; void dijkstra(){ clr(da,0x7f);da[1]=0;q.push(node(1,0)); int tx,td; while(!q.empty()){ node oo=q.top();q.pop(); tx=oo.x;td=oo.dist; if(da[tx]!=td) continue; qwq(tx) if(da[o->to]>td+o->dist){ da[o->to]=td+o->dist; q.push(node(o->to,da[o->to])); } } } void DIJKSTRA(int n){ clr(db,0x7f);db[n]=0;q.push(node(n,0)); int tx,td; while(!q.empty()){ node oo=q.top();q.pop(); tx=oo.x;td=oo.dist; if(db[tx]!=td) continue; qwq(tx) if(db[o->to]>td+o->dist){ db[o->to]=td+o->dist; q.push(node(o->to,db[o->to])); } } } void mins(int &a,int b){ if(a>b) a=b; } int main(){ int n=read(),m=read(),u,v,d; rep(i,1,m) u=read(),v=read(),d=read(),add(u,v,d); dijkstra();DIJKSTRA(n); int ans=da[n],res=inf,tmp; rep(i,1,n) qwq(i){ tmp=da[i]+db[o->to]+o->dist; if(tmp!=ans&&tmp<res) res=tmp; } rep(i,1,n) qwq(i) mins(res,da[i]+db[i]+o->dist*2); printf("%d\n",res); return 0; }
bzoj1725:嘛状压dp。。居然忘了mod居然忘了mod居然忘了mod!!!
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define clr(x,c) memset(x,c,sizeof(x)) const int mod=100000000; int sta[10005],a[15],dp[15][10005]; int main(){ int n,m,u,v,d,cnt=0;scanf("%d%d",&n,&m); rep(i,0,(1<<m)-1) if(!(i&(i<<1))) sta[++cnt]=i; rep(i,1,n) rep(j,1,m){ scanf("%d",&u); a[i]+=(1-u)*(1<<(j-1)); } rep(i,1,cnt) if(!(a[1]&sta[i])) dp[1][i]=1; rep(i,2,n) rep(j,1,cnt) if(!(a[i]&sta[j])){ rep(k,1,cnt) if(!(sta[j]&sta[k])) dp[i][j]=(dp[i][j]+dp[i-1][k])%mod; } int ans=0; rep(i,1,cnt) ans=(ans+dp[n][i])%mod; printf("%d\n",ans); return 0; }
bzoj1718:点双联通分量缩点后叶子节点个数/2就可以了。即是加最少的边让整个图双联通。将tarjan稍微修改一下就可以了。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<stack> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define clr(x,c) memset(x,c,sizeof(x)) #define qwq(x) for(edge *o=head[x];o;o=o->next) int read(){ int x=0;char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) x=x*10+c-'0',c=getchar(); return x; } const int nmax=5005; const int maxn=20005; const int inf=0x7f7f7f7f; struct edge{ int to,op;edge *next; }; edge es[maxn],*pt=es,*head[nmax]; void add(int u,int v,int cnt){ pt->to=v,pt->op=cnt,pt->next=head[u],head[u]=pt++; pt->to=u,pt->op=cnt,pt->next=head[v],head[v]=pt++; } int pre[nmax],dfs_clock=0,scc_cnt=0,sccno[nmax],in[nmax];bool vis[maxn]; stack<int>s; void mins(int &a,int b){ if(a>b) a=b; } int dfs(int x){ int lowu=pre[x]=++dfs_clock;s.push(x); qwq(x) { if(vis[o->op]) continue; if(!pre[o->to]) vis[o->op]=1,mins(lowu,dfs(o->to)); else if(!sccno[o->to]) mins(lowu,pre[o->to]); } if(lowu==pre[x]){ scc_cnt++;int tx; while(1){ tx=s.top();s.pop(); sccno[tx]=scc_cnt; if(x==tx) break; } } return lowu; } int main(){ int n=read(),m=read(),u,v; rep(i,1,m) u=read(),v=read(),add(u,v,i); dfs(1); rep(i,1,n) qwq(i) if(sccno[i]!=sccno[o->to]) in[sccno[o->to]]++; int ans=0; rep(i,1,scc_cnt) if(in[i]==1) ans++; printf("%d\n",(ans+1)>>1); return 0; }
bzoj1715:spfa判负圈就可以了,用dfs写会快。挖坑。。。没看清有向边无向边WA了。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<queue> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define clr(x,c) memset(x,c,sizeof(x)) #define qwq(x) for(edge *o=head[x];o;o=o->next) int read(){ int x=0;char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) x=x*10+c-'0',c=getchar(); return x; } const int nmax=505; const int maxn=10005; const int inf=0x7f7f7f7f; struct edge{ int to,dist;edge *next; }; edge es[maxn],*pt=es,*head[nmax]; void add(int u,int v,int d){ pt->to=v,pt->dist=d,pt->next=head[u],head[u]=pt++; } int dist[nmax],cnt[nmax];bool inq[nmax]; queue<int>q; bool spfa(int n){ clr(dist,0x7f);dist[1]=0; clr(inq,0);inq[1]=1; clr(cnt,0);cnt[1]=1; while(!q.empty()) q.pop();q.push(1); int tx; while(!q.empty()){ tx=q.front();q.pop();inq[tx]=0; qwq(tx) if(dist[o->to]>dist[tx]+o->dist){ dist[o->to]=dist[tx]+o->dist; if(!inq[o->to]) { if(++cnt[o->to]==n) return true; inq[o->to]=1;q.push(o->to); } } } return false; } int main(){ int F=read(); while(F--){ clr(head,0);pt=es; int n=read(),m=read(),w=read(),u,v,d; rep(i,1,m) u=read(),v=read(),d=read(),add(u,v,d),add(v,u,d); rep(i,1,w) u=read(),v=read(),d=read(),add(u,v,-d); if(spfa(n)) printf("YES\n"); else printf("NO\n"); } return 0; }
bzoj1710:区间dp。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define clr(x,c) memset(x,c,sizeof(x)) int read(){ int x=0;char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) x=x*10+c-'0',c=getchar(); return x; } const int nmax=2005; char s[nmax]; int a[nmax],w[30],dp[nmax][nmax]; int main(){ int m=read(),n=read();scanf("%s",s+1); rep(i,1,n) a[i]=s[i]-'a'; rep(i,1,m){ scanf("%s",s); w[s[0]-'a']=min(read(),read()); } int k; rep(i,1,n-1) { rep(j,1,n-i){ k=i+j; dp[j][k]=min(dp[j][k-1]+w[a[k]],dp[j+1][k]+w[a[j]]); if(a[j]==a[k]) dp[j][k]=min(dp[j][k],dp[j+1][k-1]); } } printf("%d\n",dp[1][n]); return 0; }
bzoj1709:暴力枚举
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define clr(x,c) memset(x,c,sizeof(x)) int read(){ int x=0;char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) x=x*10+c-'0',c=getchar(); return x; } const int nmax=105; int a[nmax][nmax],dp[nmax][nmax]; int xx[9]={0,0,0,1,1,1,-1,-1,-1}; int yy[9]={0,1,-1,1,0,-1,1,0,-1}; int main(){ int n=read(),K=read(),u,v,tx,ty; rep(i,1,K) u=read(),v=read(),a[u][v]++; rep(i,1,n) rep(j,1,n) if(a[i][j]){ rep(k,1,8) rep(t,1,n){ tx=i+xx[k]*t,ty=j+yy[k]*t; if(tx<1||ty<1||tx>n||ty>n) break; dp[tx][ty]+=a[i][j]; } dp[i][j]+=a[i][j]; } int ans=0; rep(i,1,n) rep(j,1,n) if(dp[i][j]==K) ans++; printf("%d\n",ans); return 0; }
bzoj1708:。。。背包dp。。。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define clr(x,c) memset(x,c,sizeof(x)) #define ll long long ll read(){ ll x=0;char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) x=x*10+c-'0',c=getchar(); return x; } ll a[30],dp[10005]; int main(){ int n=read(),m=read(); rep(i,1,n) a[i]=read(); dp[0]=1; rep(i,1,n) rep(j,a[i],m) dp[j]+=dp[j-a[i]]; printf("%lld\n",dp[m]); return 0; }
bzoj1707:贪心。将右端点排序后,取适合的最小spf。因为这样子取对后面的影响肯定最小!。有更优但复杂写法挖坑!。。。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) int read(){ int x=0;char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) x=x*10+c-'0',c=getchar(); return x; } const int nmax=2505; struct edge{ int l,r; bool operator<(const edge&rhs)const{ return r<rhs.r;} }; edge es[nmax]; struct node{ int spf,num; bool operator<(const node&rhs)const{ return spf<rhs.spf;} }; node ns[nmax]; int main(){ int n=read(),m=read(); rep(i,1,n) es[i].l=read(),es[i].r=read(); rep(i,1,m) ns[i].spf=read(),ns[i].num=read(); sort(es+1,es+n+1);sort(ns+1,ns+m+1); int ans=0; rep(i,1,n){ rep(j,1,m) { if(ns[j].spf>es[i].r) break; if(ns[j].spf>=es[i].l&&ns[j].num) { ns[j].num--;ans++;break; } } } printf("%d\n",ans); return 0; }
bzoj1598:A*启发式搜索+最短路求k短路
//#3哇咔咔好开心。。。 #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<queue> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define clr(x,c) memset(x,c,sizeof(x)) #define qwq(x) for(edge *o=head[x];o;o=o->next) #define qaq(x) for(edge *o=h[x];o;o=o->next) int read(){ int x=0;char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) x=x*10+c-'0',c=getchar(); return x; } const int nmax=1005; const int maxn=20005; const int inf=0x7f7f7f7f; struct edge{ int to,dist;edge *next; }; edge es[maxn],*pt=es,*head[nmax],*h[nmax]; void add(int u,int v,int d){ pt->to=v,pt->dist=d,pt->next=head[u],head[u]=pt++; pt->to=u,pt->dist=d,pt->next=h[v],h[v]=pt++; } struct node{ int x,dist; node(int x,int dist):x(x),dist(dist){}; node(){}; bool operator<(const node&rhs)const{ return dist>rhs.dist;} }; priority_queue<node>q; int dist[nmax],tm[nmax],ans[105],n,m,K; void dijkstra(){ clr(dist,0x7f);dist[1]=0;q.push(node(1,0)); node oo;int tx,td; while(!q.empty()){ oo=q.top();q.pop(); tx=oo.x,td=oo.dist; if(dist[tx]!=td) continue; qaq(tx) if(dist[o->to]>td+o->dist){ dist[o->to]=td+o->dist; q.push(node(o->to,dist[o->to])); } } } void AX(){ clr(ans,-1); if(dist[n]==inf) return ; q.push(node(n,dist[n]));node oo;int tx,td,temp; while(!q.empty()){ oo=q.top();q.pop(); tx=oo.x,td=oo.dist;temp=++tm[tx]; if(tx==1) { ans[temp]=td; if(temp==K) break; } if(temp<=K) qwq(tx) q.push(node(o->to,td-dist[tx]+dist[o->to]+o->dist)); } } int main(){ n=read(),m=read(),K=read();int u,v,d; rep(i,1,m) u=read(),v=read(),d=read(),add(u,v,d); dijkstra();AX(); rep(i,1,K) printf("%d\n",ans[i]); return 0; }
bzoj1706:离散化+矩阵快速幂 。yyl用map判重而且没用struct写矩阵乘法快了很多。不过关键是map吧。挖坑!我不会用map。。。 而且变量名短+清晰、像这里o.from,o.to,o.dist好丑啊、、、
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define clr(x,c) memset(x,c,sizeof(x)) int read(){ int x=0;char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) x=x*10+c-'0',c=getchar(); return x; } const int nmax=205; const int inf=0x3f3f3f3f; struct edge{ int from,to,dist; }; edge es[nmax]; int ns[nmax],cnt=0; void mins(int &a,int b){ if(a>b) a=b; } struct mtx{ int a[205][205]; mtx(){ clr(a,0x3f); } mtx operator*(const mtx&o)const{ mtx tmp; rep(i,1,cnt) rep(j,1,cnt) rep(k,1,cnt) mins(tmp.a[i][j],a[i][k]+o.a[k][j]); return tmp; } }a,b; int main(){ int n=read(),m=read(),s=read(),t=read(),u,v,d; rep(i,1,m) { edge &o=es[i];o.dist=read(),o.from=read(),o.to=read(); ns[++cnt]=o.from,ns[++cnt]=o.to; } sort(ns+1,ns+cnt+1); cnt=unique(ns+1,ns+cnt+1)-ns-1; rep(i,1,m) { edge &o=es[i]; o.from=lower_bound(ns+1,ns+cnt+1,o.from)-ns; o.to=lower_bound(ns+1,ns+cnt+1,o.to)-ns; b.a[o.from][o.to]=b.a[o.to][o.from]=o.dist; } n--;a=b; while(n){ if(n&1) a=a*b; n>>=1;b=b*b; } s=lower_bound(ns+1,ns+cnt+1,s)-ns; t=lower_bound(ns+1,ns+cnt+1,t)-ns; printf("%d\n",a.a[s][t]); return 0; }