#19 JOI Final 专栏

发布时间 2023-11-09 09:43:43作者: luo_shen

[JOI 2016 Final]オレンジの出荷

题面

\(f_i\) 表示 \(1\sim i\) 的都放完的最小代价,数据范围支持 \(O(nm)\) dp。

点击查看代码
#include<bits/stdc++.h>
#define ull unsigned long long
#define int long long
#define pii pair<int,int>
#define pdi pair<double,int>
#define pb push_back
#define eps 1e-9
#define mp make_pair
using namespace std;
const int inf=1e9;
namespace IO{
    template<typename T>
    inline void read(T &x){
        x=0;
        int f=1;
        char ch=getchar();
        while(ch>'9'||ch<'0'){
            if(ch=='-'){
                f=-1;
    }
            ch=getchar();
        }
        while(ch>='0'&&ch<='9'){
            x=x*10+(ch-'0');
            ch=getchar();
        }
        x=(f==1?x:-x);
    }
    template<typename T>
    inline void write(T x){
        if(x<0){
            putchar('-');
            x=-x;
        }
        if(x>=10){
            write(x/10);
        }
        putchar(x%10+'0');
    }
    template<typename T>
    inline void write_endl(T x){
        write(x);
        putchar('\n');
    }
    template<typename T>
    inline void write_space(T x){
        write(x);
        putchar(' ');
    }
}
using namespace IO;
const int N=2e4+10;
int n,m,a[N],f[N],k;
void solve(){
    read(n),read(m),read(k);
    memset(f,0x3f,sizeof(f));
    f[0]=0;
    for(int i=1;i<=n;i++){
        read(a[i]);
        int mx=a[i],mn=a[i];
        for(int j=i-1;j>=max(i-m,0ll);j--){
            f[i]=min(f[i],f[j]+(i-j)*(mx-mn)+k);
            mx=max(mx,a[j]);
            mn=min(mn,a[j]);
        }
    }
    write_endl(f[n]);
}
signed main(){
    #ifndef ONLINE_JUDGE
        freopen("1.in","r",stdin);
        freopen("1.out","w",stdout);
    #endif
    int t=1;
    while(t--){
        solve();
    }
    return 0;
}

[JOI 2016 Final]スタンプラリー 2

题面

分类讨论,加 J 直接放开头,加 I 直接放结尾,加 O 可以预处理出每个位置前面 J 和后面 I 的数量,计算出增加的贡献,容易得到最大贡献。

点击查看代码
#include<bits/stdc++.h>
#define ull unsigned long long
#define int long long
#define pii pair<int,int>
#define pdi pair<double,int>
#define pb push_back
#define eps 1e-9
#define mp make_pair
using namespace std;
const int inf=1e9;
namespace IO{
    template<typename T>
    inline void read(T &x){
        x=0;
        int f=1;
        char ch=getchar();
        while(ch>'9'||ch<'0'){
            if(ch=='-'){
                f=-1;
    }
            ch=getchar();
        }
        while(ch>='0'&&ch<='9'){
            x=x*10+(ch-'0');
            ch=getchar();
        }
        x=(f==1?x:-x);
    }
    template<typename T>
    inline void write(T x){
        if(x<0){
            putchar('-');
            x=-x;
        }
        if(x>=10){
            write(x/10);
        }
        putchar(x%10+'0');
    }
    template<typename T>
    inline void write_endl(T x){
        write(x);
        putchar('\n');
    }
    template<typename T>
    inline void write_space(T x){
        write(x);
        putchar(' ');
    }
}
using namespace IO;
const int N=1e5+10;
int n,ans,prej[N],sufi[N];
char s[N];
void solve(){
    read(n);
    for(int i=1;i<=n;i++){
        s[i]=getchar();
        while(s[i]!='J'&&s[i]!='O'&&s[i]!='I'){
            s[i]=getchar();
        }
        prej[i]=prej[i-1]+(s[i]=='J');
    }
    for(int i=n;i;i--){
        sufi[i]=sufi[i+1]+(s[i]=='I');
    }
    int cnti=0,cntoi=0,nowans=0;
    for(int i=n;i;i--){
        if(s[i]=='I'){
            cnti++;
        }
        else if(s[i]=='O'){
            cntoi+=cnti;
        }
        else{
            nowans+=cntoi;
        }
    }
    ans=max(ans,nowans+cntoi);
    cnti=1,cntoi=0,nowans=0;
    for(int i=n;i;i--){
        if(s[i]=='I'){
            cnti++;
        }
        else if(s[i]=='O'){
            cntoi+=cnti;
        }
        else{
            nowans+=cntoi;
        }
    }
    ans=max(ans,nowans);
    cnti=0,cntoi=0,nowans=0;
    for(int i=n;i;i--){
        if(s[i]=='I'){
            cnti++;
        }
        else if(s[i]=='O'){
            cntoi+=cnti;
        }
        else{
            nowans+=cntoi;
        }
    }
    for(int i=1;i<=n;i++){
        ans=max(ans,nowans+prej[i]*sufi[i+1]);
    }
    write_endl(ans);
}
signed main(){
    #ifndef ONLINE_JUDGE
        freopen("1.in","r",stdin);
        freopen("1.out","w",stdout);
    #endif
    int t=1;
    while(t--){
        solve();
    }
    return 0;
}

鉄道運賃

题面

有一个显而易见的结论:任意时刻,一条从起点到一个满意的城市的路不会经过一条升过价的路,所以涨价等价于将这条路断掉。

断边不好处理,考虑反过来,断边转加边。但是不能每加一条边都全图重做求最短路,需要找到影响的点有哪些,从加的边的端点开始更新,只有当更新后的最短路为原图中的最短路时,再继续更新,否则等更新的路为原图中的最短路时更新肯定不劣,每个点最多更新一回,复杂度 \(O(n\log m+n)\)

点击查看代码
#include<bits/stdc++.h>
#define ull unsigned long long
#define ll long long
#define pii pair<int,int>
#define pdi pair<double,int>
#define pb push_back
#define eps 1e-9
#define mp make_pair
using namespace std;
const int inf=1e9;
namespace IO{
    template<typename T>
    inline void read(T &x){
        x=0;
        int f=1;
        char ch=getchar();
        while(ch>'9'||ch<'0'){
            if(ch=='-'){
                f=-1;
    }
            ch=getchar();
        }
        while(ch>='0'&&ch<='9'){
            x=x*10+(ch-'0');
            ch=getchar();
        }
        x=(f==1?x:-x);
    }
    template<typename T>
    inline void write(T x){
        if(x<0){
            putchar('-');
            x=-x;
        }
        if(x>=10){
            write(x/10);
        }
        putchar(x%10+'0');
    }
    template<typename T>
    inline void write_endl(T x){
        write(x);
        putchar('\n');
    }
    template<typename T>
    inline void write_space(T x){
        write(x);
        putchar(' ');
    }
}
using namespace IO;
const int N=1e5+10,M=2e5+10;
int n,m,q,u[M],v[M],r[M],lim[M<<1],d[N][2],vis[N],ans[M],tot,head[N],cnt=1;
struct edge{
    int v,nxt;
}e[M<<1];
void add(int u,int v){
    e[++tot].v=v;
    e[tot].nxt=head[u];
    head[u]=tot;
}
void bfs(int id){
    queue<int>q;
    for(int i=1;i<=n;i++){
        d[i][id]=inf;
        vis[i]=0;
    }
    q.push(1);
    d[1][id]=0;
    vis[1]=1;
    while(q.size()){
        int u=q.front();
        q.pop();
        for(int i=head[u];i;i=e[i].nxt){
            int v=e[i].v;
            if(vis[v]||lim[i]){
                continue;
            }
            vis[v]=1;
            d[v][id]=d[u][id]+1;
            q.push(v);
        }
    }
}
void change(int x,int y){
    int Max=max(d[x][1],d[y][1]),Min=min(d[x][1],d[y][1]);
    if(Max==Min||Max==Min+1){
        return;
    }
    if(d[x][1]>d[y][1]){
        swap(x,y);
    }
    d[y][1]=d[x][1]+1;
    if(d[y][1]!=d[y][0]){
        return;
    }
    queue<int>q;
    q.push(y);
    for(int i=1;i<=n;i++){
        vis[i]=0;
    }
    while(!q.empty()){
        int u=q.front();
        q.pop();
        cnt++;
        for(int i=head[u];i;i=e[i].nxt){
            int v=e[i].v;
            if(vis[v]||lim[i]||d[v][1]<=d[u][1]+1){
                continue;
            }
            vis[v]=1;
            d[v][1]=d[u][1]+1;
            if(d[v][1]==d[v][0]){
                q.push(v);
            }
        }
    }
}
void solve(){
    read(n),read(m),read(q);
    for(int i=1;i<=m;i++){
        read(u[i]),read(v[i]);
        add(u[i],v[i]);
        add(v[i],u[i]);
    }
    for(int i=1;i<=q;i++){
        read(r[i]);
    }
    bfs(0);
    for(int i=1;i<=q;i++){
        lim[r[i]*2]=lim[r[i]*2-1]=1;
    }
    bfs(1);
    for(int i=2;i<=n;i++){
        if(d[i][0]==d[i][1]){
            cnt++;
        }
    }
    for(int i=q;i;i--){
        ans[i]=n-cnt;
        lim[r[i]*2-1]=lim[r[i]*2]=0;
        int x=u[r[i]],y=v[r[i]];
        change(x,y);
    }
    for(int i=1;i<=q;i++){
        write_endl(ans[i]);
    }
}
signed main(){
    #ifndef ONLINE_JUDGE
        freopen("1.in","r",stdin);
        freopen("1.out","w",stdout);
    #endif
    int t=1;
    while(t--){
        solve();
    }
    return 0;
}

[JOI 2017 Final]フェーン現象

题面

因为温度和高度差有关,对原数组做差分,在差分数组上所有的修改操作直接区间转单点了。

点击查看代码
#include<bits/stdc++.h>
#define ull unsigned long long
#define int long long
#define pii pair<int,int>
#define pdi pair<double,int>
#define pb push_back
#define eps 1e-9
#define mp make_pair
using namespace std;
const int inf=1e9;
namespace IO{
    template<typename T>
    inline void read(T &x){
        x=0;
        int f=1;
        char ch=getchar();
        while(ch>'9'||ch<'0'){
            if(ch=='-'){
                f=-1;
    }
            ch=getchar();
        }
        while(ch>='0'&&ch<='9'){
            x=x*10+(ch-'0');
            ch=getchar();
        }
        x=(f==1?x:-x);
    }
    template<typename T>
    inline void write(T x){
        if(x<0){
            putchar('-');
            x=-x;
        }
        if(x>=10){
            write(x/10);
        }
        putchar(x%10+'0');
    }
    template<typename T>
    inline void write_endl(T x){
        write(x);
        putchar('\n');
    }
    template<typename T>
    inline void write_space(T x){
        write(x);
        putchar(' ');
    }
}
using namespace IO;
const int N=2e5+10;
int n,q,s,t,a[N];
int val(int x){
    if(x>0){
        return x*t;
    }
    if(x<0){
        return x*s;
    }
    return 0;
}
void solve(){
    read(n),read(q),read(t),read(s);
    t=-t,s=-s;
    int ans=0;
    read(a[0]);
    for(int i=1;i<=n;i++){
        read(a[i]);
    }
    for(int i=n;i;i--){
        a[i]=a[i]-a[i-1];
        ans+=val(a[i]);
    }
    while(q--){
        int l,r,v;
        read(l),read(r),read(v);
        ans-=val(a[l]);
        a[l]+=v;
        ans+=val(a[l]);
        if(r<n){
            ans-=val(a[r+1]);
            a[r+1]-=v;
            ans+=val(a[r+1]);
        }
        write_endl(ans);
    }
}
signed main(){
    #ifndef ONLINE_JUDGE
        freopen("1.in","r",stdin);
        freopen("1.out","w",stdout);
    #endif
    int t=1;
    while(t--){
        solve();
    }
    return 0;
}

[JOI 2017 Final]JOIOI 王国

题面

最小值 \(mn\) 和最大值 \(mx\) 显然不在一个集合中,不然答案固定。二分答案,判断根据题目描述,形成的图形一定为阶梯型,分四种情况讨论,判断是否存在包含 \(mn\) 的块里的数都小于等于 \(mn+x\),包含 \(mx\) 的块里的数都大于等于 \(mx-x\)

点击查看代码
#include<bits/stdc++.h>
#define ull unsigned long long
#define ll long long
#define pii pair<int,int>
#define pdi pair<double,int>
#define pb push_back
#define eps 1e-9
#define mp make_pair
using namespace std;
const int inf=1e9;
namespace IO{
    template<typename T>
    inline void read(T &x){
        x=0;
        int f=1;
        char ch=getchar();
        while(ch>'9'||ch<'0'){
            if(ch=='-'){
                f=-1;
    }
            ch=getchar();
        }
        while(ch>='0'&&ch<='9'){
            x=x*10+(ch-'0');
            ch=getchar();
        }
        x=(f==1?x:-x);
    }
    template<typename T>
    inline void write(T x){
        if(x<0){
            putchar('-');
            x=-x;
        }
        if(x>=10){
            write(x/10);
        }
        putchar(x%10+'0');
    }
    template<typename T>
    inline void write_endl(T x){
        write(x);
        putchar('\n');
    }
    template<typename T>
    inline void write_space(T x){
        write(x);
        putchar(' ');
    }
}
using namespace IO;
const int N=2010;
int n,m,a[N][N],mn=inf,mx=-inf,Mn[N],Mx[N];
bool check(int x){
    bool flag=1;
    Mn[0]=Mx[n+1]=-inf,Mn[0]=Mn[n+1]=inf;
    for(int i=1;i<=n;i++){
        Mn[i]=Mn[i-1];
        for(int j=1;j<=m;j++){
            if(a[i][j]>mn+x){
                Mn[i]=min(Mn[i],j);
            }
        }
    }
    for(int i=n;i;i--){
        Mx[i]=Mx[i+1];
        for(int j=1;j<=m;j++){
            if(a[i][j]<mx-x){
                Mx[i]=max(Mx[i],j);
            }
        }
        if(Mx[i]>=Mn[i]){
            flag=0;
        }
    }
    if(flag){
        return 1;
    }
    flag=1;
    for(int i=1;i<=n;i++){
        Mn[i]=Mn[i-1];
        for(int j=1;j<=m;j++){
            if(a[i][j]<mx-x){
                Mn[i]=min(Mn[i],j);
            }
        }
    }
    for(int i=n;i;i--){
        Mx[i]=Mx[i+1];
        for(int j=1;j<=m;j++){
            if(a[i][j]>mn+x){
                Mx[i]=max(Mx[i],j);
            }
        }
        if(Mx[i]>=Mn[i]){
            flag=0;
        }
    }
    if(flag){
        return 1;
    }
    flag=1;
    for(int i=n;i;i--){
        Mn[i]=Mn[i+1];
        for(int j=1;j<=m;j++){
            if(a[i][j]<mx-x){
                Mn[i]=min(Mn[i],j);
            }
        }
    }
    for(int i=1;i<=n;i++){
        Mx[i]=Mx[i-1];
        for(int j=1;j<=m;j++){
            if(a[i][j]>mn+x){
                Mx[i]=max(Mx[i],j);
            }
        }
        if(Mx[i]>=Mn[i]){
            flag=0;
        }
    }
    if(flag){
        return 1;
    }
    flag=1;
    for(int i=n;i;i--){
        Mn[i]=Mn[i+1];
        for(int j=1;j<=m;j++){
            if(a[i][j]>mn+x){
                Mn[i]=min(Mn[i],j);
            }
        }
    }
    for(int i=1;i<=n;i++){
        Mx[i]=Mx[i-1];
        for(int j=1;j<=m;j++){
            if(a[i][j]<mx-x){
                Mx[i]=max(Mx[i],j);
            }
        }
        if(Mx[i]>=Mn[i]){
            flag=0;
        }
    }
    if(flag){
        return 1;
    }
    return 0;
}
void solve(){
    read(n),read(m);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            read(a[i][j]);
            mx=max(mx,a[i][j]);
            mn=min(mn,a[i][j]);
        }
    }
    int l=0,r=mx-mn,ans;
    while(l<=r){
        int mid=(l+r)>>1;
        if(check(mid)){
            r=mid-1;
            ans=mid;
        }
        else{
            l=mid+1;
        }
    }
    write_endl(ans);
}
signed main(){
    #ifndef ONLINE_JUDGE
        freopen("1.in","r",stdin);
        freopen("1.out","w",stdout);
    #endif
    int t=1;
    while(t--){
        solve();
    }
    return 0;
}

[JOI 2018 Final]美術展

题面

按大小排序,如果已经选定了最大的和最小的,中间的肯定都可以选,它们只会影响价值和,答案不降。将贡献拆开,令 \(b_i\) 表示价值的前缀和,\(S-a_{\max}+a_{\min}=b_{i}-a_i+a_j-b_{j-1}\),求出 \(a_j-b_{j-1}\) 的前缀最大值即可计算。

点击查看代码
#include<bits/stdc++.h>
#define ull unsigned long long
#define int long long
#define pii pair<int,int>
#define pdi pair<double,int>
#define pb push_back
#define eps 1e-9
#define mp make_pair
using namespace std;
const int inf=1e18;
namespace IO{
    template<typename T>
    inline void read(T &x){
        x=0;
        int f=1;
        char ch=getchar();
        while(ch>'9'||ch<'0'){
            if(ch=='-'){
                f=-1;
    }
            ch=getchar();
        }
        while(ch>='0'&&ch<='9'){
            x=x*10+(ch-'0');
            ch=getchar();
        }
        x=(f==1?x:-x);
    }
    template<typename T>
    inline void write(T x){
        if(x<0){
            putchar('-');
            x=-x;
        }
        if(x>=10){
            write(x/10);
        }
        putchar(x%10+'0');
    }
    template<typename T>
    inline void write_endl(T x){
        write(x);
        putchar('\n');
    }
    template<typename T>
    inline void write_space(T x){
        write(x);
        putchar(' ');
    }
}
using namespace IO;
const int N=5e5+10;
int n,b[N];
pii a[N];
void solve(){
    read(n);
    for(int i=1;i<=n;i++){
        read(a[i].first),read(a[i].second);
    }
    sort(a+1,a+n+1);
    for(int i=1;i<=n;i++){
        b[i]=b[i-1]+a[i].second;
    }
    int mx=-inf,ans=-inf;
    for(int i=1;i<=n;i++){
        mx=max(mx,a[i].first-b[i-1]);
        ans=max(ans,mx+b[i]-a[i].first);
    }
    write_endl(ans);
}
signed main(){
    #ifndef ONLINE_JUDGE
        freopen("1.in","r",stdin);
        freopen("1.out","w",stdout);
    #endif
    int t=1;
    while(t--){
        solve();
    }
    return 0;
}

[JOI 2018 Final]団子職人

题面

如果两个团子冲突,则两个团子的 G 必然都在一条左下到右上的的斜线上。枚举斜线,令 \(f_{i,0/1/2}\) 表示在斜线上的该点的团子没有/是横着/是竖着,直接dp即可。

点击查看代码
#include<bits/stdc++.h>
#define ull unsigned long long
#define ll long long
#define pii pair<int,int>
#define pdi pair<double,int>
#define pb push_back
#define eps 1e-9
#define mp make_pair
using namespace std;
const int inf=1e9;
namespace IO{
    template<typename T>
    inline void read(T &x){
        x=0;
        int f=1;
        char ch=getchar();
        while(ch>'9'||ch<'0'){
            if(ch=='-'){
                f=-1;
    }
            ch=getchar();
        }
        while(ch>='0'&&ch<='9'){
            x=x*10+(ch-'0');
            ch=getchar();
        }
        x=(f==1?x:-x);
    }
    template<typename T>
    inline void write(T x){
        if(x<0){
            putchar('-');
            x=-x;
        }
        if(x>=10){
            write(x/10);
        }
        putchar(x%10+'0');
    }
    template<typename T>
    inline void write_endl(T x){
        write(x);
        putchar('\n');
    }
    template<typename T>
    inline void write_space(T x){
        write(x);
        putchar(' ');
    }
}
using namespace IO;
const int N=3e3+10;
int n,m,ans,f[N][3];
char ch[N][N];
void solve(){
    read(n),read(m);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            ch[i][j]=getchar();
            while(ch[i][j]!='R'&&ch[i][j]!='G'&&ch[i][j]!='W'){
                ch[i][j]=getchar();
            }
        }
    }
    for(int s=2;s<=n+m;s++){
        memset(f,0,sizeof(f));
        int tmp=0;
        for(int i=max(1,s-m),j=s-i;i<=n&&j;i++,j--){
            f[i][0]=max(max(f[i-1][0],f[i-1][1]),f[i-1][2]);
            if(ch[i][j]=='G'){
                if(ch[i-1][j]=='R'&&ch[i+1][j]=='W'){
                    f[i][1]=max(f[i][1],max(f[i-1][0],f[i-1][1])+1);
                }
                if(ch[i][j-1]=='R'&&ch[i][j+1]=='W'){
                    f[i][2]=max(f[i][2],max(f[i-1][0],f[i-1][2])+1);
                }
            }
            tmp=max(tmp,max(max(f[i][0],f[i][1]),f[i][2]));
        }
        ans+=tmp;
    }
    write_endl(ans);
}
signed main(){
    #ifndef ONLINE_JUDGE
        freopen("1.in","r",stdin);
        freopen("1.out","w",stdout);
    #endif
    int t=1;
    while(t--){
        solve();
    }
    return 0;
}

[JOI 1018 Final]定期券

题面

一个显而易见的结论是两条路径只有一段重叠的。证明很容易,若 \(A\rightarrow B\rightarrow C\rightarrow D\),其中 \(A\rightarrow B,C\rightarrow D\) 在最短路上,\(B\rightarrow C\) 不在最短路上,不如直接换成最短路上的路径上的路,因此只会有一段路径,这段路径要么正着经过要么反着经过,直接找到所有最短路上的边,正边建一层图,反边建一层图,跑分层图即可得到答案。

点击查看代码
#include<bits/stdc++.h>
#define ull unsigned long long
#define int long long
#define pii pair<int,int>
#define pdi pair<double,int>
#define pb push_back
#define eps 1e-9
#define mp make_pair
using namespace std;
const int inf=1e18;
namespace IO{
    template<typename T>
    inline void read(T &x){
        x=0;
        int f=1;
        char ch=getchar();
        while(ch>'9'||ch<'0'){
            if(ch=='-'){
                f=-1;
    }
            ch=getchar();
        }
        while(ch>='0'&&ch<='9'){
            x=x*10+(ch-'0');
            ch=getchar();
        }
        x=(f==1?x:-x);
    }
    template<typename T>
    inline void write(T x){
        if(x<0){
            putchar('-');
            x=-x;
        }
        if(x>=10){
            write(x/10);
        }
        putchar(x%10+'0');
    }
    template<typename T>
    inline void write_endl(T x){
        write(x);
        putchar('\n');
    }
    template<typename T>
    inline void write_space(T x){
        write(x);
        putchar(' ');
    }
}
using namespace IO;
const int M=2e5+10,N=4e5+10;
int n,m,s,t,st,ed,head[N],fir[N],tot,cnt,vis[N],d[N],c[N];
struct edge{
    int u,v,w,nxt;
}e[M<<1],G[M<<4];
void add(int u,int v,int w){
    e[++tot].v=v;
    e[tot].u=u;
    e[tot].w=w;
    e[tot].nxt=head[u];
    head[u]=tot;
}
void ins(int u,int v,int w){
    G[++cnt].v=v;
    G[cnt].w=w;
    G[cnt].nxt=fir[u];
    fir[u]=cnt;
}
void dij(){
    for(int i=1;i<=n;i++){
        vis[i]=0;
        d[i]=inf;
    }
    d[s]=0;
    priority_queue<pii>q;
    q.push(mp(0,s));
    while(!q.empty()){
        int u=q.top().second;
        q.pop();
        if(vis[u]){
            continue;
        }
        vis[u]=1;
        for(int i=head[u];i;i=e[i].nxt){
            int v=e[i].v,w=e[i].w;
            if(d[v]>d[u]+w){
                d[v]=d[u]+w;
                q.push(mp(-d[v],v));
            }
        }
    }
    for(int i=1;i<=n;i++){
        vis[i]=0;
        c[i]=inf;
    }
    c[t]=0;
    q.push(mp(0,t));
    while(!q.empty()){
        int u=q.top().second;
        q.pop();
        if(vis[u]){
            continue;
        }
        vis[u]=1;
        for(int i=head[u];i;i=e[i].nxt){
            int v=e[i].v,w=e[i].w;
            if(c[v]>c[u]+w){
                c[v]=c[u]+w;
                q.push(mp(-c[v],v));
            }
        }
    }
    for(int u=1;u<=n;u++){
        for(int i=head[u];i;i=e[i].nxt){
            int v=e[i].v,w=e[i].w;
            if(d[u]+c[v]+w==d[t]){
                ins(u+n,v+n,0);
                ins(v+n*2,u+n*2,0);
            }
        }
    }
}
void work(){
    for(int i=1;i<=n*4;i++){
        d[i]=inf;
        vis[i]=0;
    }
    d[st]=0;
    priority_queue<pii>q;
    q.push(mp(0,st));
    while(!q.empty()){
        int u=q.top().second;
        q.pop();
        for(int i=fir[u];i;i=G[i].nxt){
            int v=G[i].v,w=G[i].w;
            if(d[v]>d[u]+w){
                d[v]=d[u]+w;
                q.push(mp(-d[v],v));
            }
        }
    }
    write_endl(d[ed+3*n]);
}
void solve(){
    read(n),read(m);
    read(s),read(t);
    read(st),read(ed);
    for(int i=1;i<=m;i++){
        int u,v,w;
        read(u),read(v),read(w);
        add(u,v,w);
        add(v,u,w);
        ins(u,v,w);
        ins(v,u,w);
        ins(u+n*3,v+n*3,w);
        ins(v+n*3,u+n*3,w);
    }
    for(int i=1;i<=n;i++){
        ins(i,i+n,0);
        ins(i,i+n*2,0);
        ins(i+n,i+n*3,0);
        ins(i+n*2,i+n*3,0);
    }
    dij();
    work();
}
signed main(){
    #ifndef ONLINE_JUDGE
        freopen("1.in","r",stdin);
        freopen("1.out","w",stdout);
    #endif
    int t=1;
    while(t--){
        solve();
    }
    return 0;
}