제출 #1334154

#제출 시각아이디문제언어결과실행 시간메모리
1334154AquariusRobot (JOI21_ho_t4)C++17
100 / 100
1053 ms124152 KiB
#include<bits/stdc++.h>
#define int long long
#define sz(x) (int) x.size()
#define all(x) x.begin(), x.end()
using namespace std;


const int N = 1e5+5;
const int INF = 1e17;



struct Infor{
    int u, c, w;
};

vector<Infor> E[2*N];
map<int,vector<pair<int,int>>>  E_color[2*N];


int dp[N];
map<int,int> dp2[N];
map<int,int> color[N], sum[N];
int n, m;

/*
đi từ u -> v bằng cạnh màu c , trọng số w

(Ta sẽ đổi màu các cạnh còn lại kết nối với u có màu c)
dp[v] = dp[u] + sum[u][c] - w



đi từ u --> v bằng cách đổi màu c của canh với trọng số w

dp[v] = dp[u] + w


đi từ u --> v bằng cách dổi màu c của cạnh với trọng số w, tuy nhiên khi ta đi tiếp từ v sang cạnh có màu c.

Thì do đổi màu c của cạnh hiện tại rồi nên nó không làm ảnh hưởng đến cạnh phía sau và ta có thể đi qua cạnh này mà
không tốn chi phí, vậy ta sẽ khoang tạm tính trọng số của việc đổi cạnh này mà để sang v tính

dp2[v][c] = dp[u]


Từ đỉnh v chưa tính trọng số của việc đổi màu cạnh trước đó ta buocj phải đi qua cạnh có màu


*/


struct Node {
    int d, u, type;
    bool operator<(const Node &other) const{
        return d >other.d;
    }

};

void Dijkstra() {
    fill(dp, dp+n+1, INF);
    priority_queue<Node> pq;

    pq.push({0, 1, 0});

    dp[1] = 0;

    while(!pq.empty()) {
        Node res = pq.top(); pq.pop();
        int u = res.u;
        int d = res.d;
        int type = res.type;
        if(type == 0) {
            if(d > dp[u]) continue;
            for(Infor &tmp: E[u]) {
                int w = tmp.w;
                int v = tmp.u;
                int c = tmp.c;

                if(dp[v] > dp[u] + sum[u][c] - w) {
                    dp[v] = dp[u] + sum[u][c] - w;
                    pq.push({dp[v], v, 0});
                }

                if(dp[v] > dp[u] + w) {
                    dp[v] = dp[u] + w;
                    pq.push({dp[v], v, 0});
                }

                if(!dp2[v].count(c) || dp2[v][c]  > dp[u]) {
                    dp2[v][c] = dp[u];
                    pq.push({dp[v], v, c});
                }

            }

        }
        else {
            if(d < dp2[u][type]) continue;
            for(pair<int,int> &tmp: E_color[u][type]) {
                int v = tmp.first;
                int w = tmp.second;
                if(dp[v] > dp2[u][type] + sum[u][type] - w) {
                    dp[v] = dp2[u][type] + sum[u][type] - w;
                    pq.push({dp[v], v, 0});
                }

            }

        }

    }

}



void solve() {
    cin >> n >> m;


    for(int i=1; i<=m; i++) {

        int u, v, c, p;  cin >> u >> v >> c >> p;
        E[u].push_back({v, c, p});
        E[v].push_back({u, c, p});
        E_color[u][c].push_back({v, p});
        E_color[v][c].push_back({u, p});
        color[u][c]++;
        color[v][c]++;
        sum[u][c] += p;
        sum[v][c] += p;
    }


    Dijkstra();

    cout << (dp[n] == INF ? -1: dp[n]) <<'\n';

}

signed main() {
    if(fopen("input.txt", "r")) freopen("input.txt", "r", stdin);
    ios_base::sync_with_stdio(false);cin.tie(0);
    int T = 1;
//    cin >> T;
    while(T--) solve();
}

컴파일 시 표준 에러 (stderr) 메시지

Main.cpp: In function 'int main()':
Main.cpp:144:40: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  144 |     if(fopen("input.txt", "r")) freopen("input.txt", "r", stdin);
      |                                 ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...