제출 #1328060

#제출 시각아이디문제언어결과실행 시간메모리
1328060joacruRobot (JOI21_ho_t4)C++20
100 / 100
447 ms61832 KiB
#include <iostream>
#include <assert.h>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>

#define forn(i,n) for(int i=0;i<(int)n;++i)
#define fort(i,n) for(int i=0;i<=(int)n;++i)
#define fori(i,a,n) for(int i=a;i<(int)n;++i)
#define forit(i,a,n) for(int i=a;i<=(int)n;++i)

#define DBG(a) cerr<<#a<<" = "<<(a)<<endl
#define DBGA(a) cerr<<#a<<" = "<<(a)<<", ";
#define DBG2(a,b) do{DBGA(a)DBG(b);}while(0)
#define DBG3(a,b,c) do{DBGA(a)DBGA(b)DBG(c);}while(0)
#define DBG4(a,b,c,d) do{DBGA(a)DBGA(b)DBGA(c)DBG(d);}while(0)

#define ALL(v) v.begin(),v.end()
#define SZ(v) (int)v.size()

using namespace std;

template<typename T>
ostream &operator<<(ostream &os, vector<T> v){
	os<<"[";
	forn(i,SZ(v)){
		if(i) os<<", ";
		os<<v[i];
	}
	os<<"]";
	return os;
}

template<typename T>
using PQ = priority_queue<T>;

typedef long long ll;

const ll INF = 1000000000000000000;

struct Edge{
	int v, p;
};

struct State{
	int u, c; // color que tiene que aprovechar
	ll d;
	bool operator<(const State &o)const{
		return d>o.d;
	}
};

void solve(){
	
	int n, m;
	cin>>n>>m;
	
	map<int,vector<Edge>> g[n];
	
	forn(i,m){
		int u, v, c, p;
		cin>>u>>v>>c>>p;
		--u,--v;
		g[u][c].push_back({v,p});
		g[v][c].push_back({u,p});
	}
	
	map<int,ll> dist[n];
	PQ<State> dij;
	dist[0][0] = 0;
	dij.push({0,0,0});
	
	while(SZ(dij)){
		int u=dij.top().u, c=dij.top().c;
		ll d=dij.top().d;
		dij.pop();
		if(dist[u][c] != d) continue;
		//~ DBG3(u,c,d);
		if(!c){ // no tiene un color definido para aprovechar
			for(const auto &color: g[u]){ // por color
				if(!dist[u].count(color.first) || d < dist[u][color.first]){
					dist[u][color.first] = d;
					dij.push({u,color.first,d});
				}
				int x = (SZ(color.second) > 1);
				for(auto [v,p]: color.second){ // prueba lo siguiente sin problema
					ll nd = d + p * x; // solo suma si hay más de uno
					if(!dist[v].count(0) || nd < dist[v][0]){
						dist[v][0] = nd;
						dij.push({v,0,nd});
					}
					nd = d; // no aumenta con la promesa de que lo va a usar despues
					if(!dist[v].count(color.first) || nd < dist[v][color.first]){
						dist[v][color.first] = nd;
						dij.push({v,color.first,nd});
					}
				}
			}
		} else{ // tiene que aprovechar el color sí o sí
			ll sum = 0;
			for(auto [v,p]: g[u][c]){
				sum += p;
			}
			for(auto [v,p]: g[u][c]){
				ll nd = d + sum - p; // cambio el color de todo menos del que voy a atravesar
				if(!dist[v].count(0) || nd < dist[v][0]){
					dist[v][0] = nd;
					dij.push({v,0,nd});
				}
			}
		}
	}
	
	ll ans = -1;
	if(dist[n-1].count(0)) ans = dist[n-1][0];
	cout<<ans<<"\n";
	
}

int main(){
	
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	
	#ifdef LOCAL
	freopen("D.in", "r", stdin);
	int tcs;
	cin>>tcs;
	while(tcs--)
	#endif
	solve();
	
	return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...