제출 #393537

#제출 시각아이디문제언어결과실행 시간메모리
393537nohaxjustsofloCommuter Pass (JOI18_commuter_pass)C++17
100 / 100
854 ms56872 KiB
#include <bits/stdc++.h>
typedef long long ll;

using namespace std;
const int mxN = 1e5+5;
const int mxM = 2e5+5;

struct edge
{
    int u, v;
    ll c;
    int rev;
};

vector<int> out[mxN];
vector<int> in[mxN];
vector<int> new_out[mxN];
vector<int> new_in[mxN];
edge edges[2*mxM];
ll best[mxN];
bool ok[mxN]; ///vertices on shortest path
bool done[mxN];
bool cut[2*mxM];

bool fix(int i, int t)
{
    if(i == t) return true;
    if(done[i]) return ok[i];
    done[i] = true;
    for(int e : out[i])
    {
        int j = edges[e].v;
        if(cut[e]) continue;
        if(fix(j, t))
        {
            ok[i]=1;
            new_out[i].push_back(e);
            new_in[j].push_back(edges[e].rev);
        }
    }
    return ok[i];
}

/// node, used, using, direction
ll dp[mxN][2][2][2];

struct pos
{
    int i, used, cur, dir;
    bool operator<(const pos& p) const
    {
        return i < p.i;
    }
};

ll solve(int u, int v)
{
    for(int i = 0; i < mxN; i++)
        for(int j = 0; j < 2; j++)
            for(int k = 0; k < 2; k++)
                dp[i][j][k][0] = dp[i][j][k][1] = 1e18;

    ll ans = 1e18;
    dp[u][0][0][0] = 0;
    priority_queue<pair<ll, pos>> q;
    q.push({0, {u, 0, 0, 0}});
    while(!q.empty())
    {
        auto par = q.top(); q.pop();
        pos p = par.second;
        int i = p.i;
        ll cost = -par.first;
        if(cost > dp[p.i][p.used][p.cur][p.dir]) continue;
        if(i == v)
        {
            ans = min(ans, cost);
            continue;
        }
        if(!p.used)
        {
            if(!p.cur || !p.dir)
            {
                for(auto e : new_out[i]) ///kreni u 0 dir
                {
                    int j = edges[e].v;
                    if(cost < dp[j][0][1][0])
                    {
                        dp[j][0][1][0] = cost;
                        q.push({-cost, {j, 0, 1, 0}});
                    }
                }
            }
            if(!p.cur || p.dir)
            {
                for(auto e : new_in[i]) ///kreni u 1 dir
                {
                    int j = edges[e].v;
                    if(cost < dp[j][0][1][1])
                    {
                        dp[j][0][1][1] = cost;
                        q.push({-cost, {j, 0, 1, 1}});
                    }
                }
            }
            if(p.cur)
            {
                for(auto e : out[i]) ///canceluj
                {
                    int j = edges[e].v;
                    if(cost + edges[e].c < dp[j][1][0][0])
                    {
                        dp[j][1][0][0] = cost + edges[e].c;
                        q.push({-dp[j][1][0][0], {j,1,0,0}});
                    }
                }
            }
            else
            {
                for(auto e : out[i]) ///klasicno samo nastavi !used
                {
                    int j = edges[e].v;
                    if(cost + edges[e].c < dp[j][0][0][0])
                    {
                        dp[j][0][0][0] = cost + edges[e].c;
                        q.push({-dp[j][0][0][0], {j,0,0,0}});
                    }
                }
            }
        }
        else
        {
            for(auto e : out[i]) ///klasicno samo nastavi used
            {
                int j = edges[e].v;
                if(cost + edges[e].c < dp[j][1][0][0])
                {
                    dp[j][1][0][0] = cost + edges[e].c;
                    q.push({-dp[j][1][0][0], {j,1,0,0}});
                }
            }
        }
    }
    return ans;
}

int main()
{
    for(int i = 0; i < mxN; i++) best[i] = 1e18;
    int n, m;
    cin >> n >> m;
    int s, t, U, V;
    cin >> s >> t >> U >> V;
    for(int i = 0; i < m; i++)
    {
        int u, v; ll c; cin >> u >> v >> c;
        edges[i*2] = {u,v,c,i*2+1};
        edges[i*2+1] = {v,u,c,i*2};
        out[u].push_back(i*2);
        in[u].push_back(i*2+1);
        out[v].push_back(i*2+1);
        in[v].push_back(i*2);
    }
    best[s] = 0;
    ///cost, to, edge
    priority_queue<pair<ll, int>> q;
    q.push({0, s});
    while(!q.empty())
    {
        auto cur = q.top(); q.pop();
        int i = cur.second;
        int cost = -cur.first;
        if(cost > best[i]) continue;
        for(auto e : in[i])
        {
            int u = edges[e].u, v = i;
            ll c = edges[e].c;
            if(best[u] + c > best[v]) cut[e] = true;
        }
        for(auto e : out[i])
        {
            int u = i, v = edges[e].v;
            ll c = edges[e].c;
            if(best[u] + c < best[v])
            {
                best[v] = best[u] + c;
                q.push({-best[v], v});
            }
        }
    }
    fix(s, t);
    /*for(int i = 1; i <= n; i++)
    {
        cout << "node " << i << "\n";
        for(int e : new_out[i])
        {
            cout << edges[e].c << " ";
        }
        cout << "\n";
    }
    cout << "*********************************\n";
    for(int i = 1; i <= n; i++)
    {
        cout << "node " << i << "\n";
        for(int e : new_in[i])
        {
            cout << edges[e].u << edges[e].v << " ";
        }
        cout << "\n";
    }
    cout<<"\n\n";*/
    cout << solve(U, V);
}
/*
6 6
1 6
1 4
1 2 1
2 3 1
3 5 1
2 4 3
4 5 2
6 5 1

4 4
1 4
0 0
1 2 1
1 3 1
2 4 1
3 4 1
*/
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...