Submission #58655

#TimeUsernameProblemLanguageResultExecution timeMemory
58655ksun48Wild Boar (JOI18_wild_boar)C++14
12 / 100
412 ms3036 KiB
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;

const LL MAXD = (1LL << 60LL);
int n, m, t, l;
vector<int> a, b;
vector<LL> c;
typedef pair<LL, pair<int,int> > Path;
typedef vector<Path> OptPaths;
int unused = 3000;

Path new_unused(){
	Path x = {MAXD, {unused,unused}};
	//unused ++;
	return x;
}

Path alt_path(pair<int,int> avoid, OptPaths& paths){
	for(Path x : paths){
		if(x.second.first != avoid.first && x.second.second != avoid.second) return x;
	}
	return new_unused();
}

int np = 0;
OptPaths process(OptPaths cand){
	np++;
	OptPaths edges;

	if(cand.size() == 0) return edges;
	sort(cand.begin(), cand.end());

	pair<int,int> x = cand[0].second;
	edges.push_back(cand[0]);
	pair<int,int> y;
	for(int i = 0; i < cand.size(); i++){
		if(cand[i].second == x) continue;
		y = cand[i].second;
		edges.push_back(cand[i]);
		break;
	}
	if(edges.size() == 1){
		return edges;
	}

	if(x.first != y.first && x.second != y.second){
		edges.push_back(alt_path({x.first, y.second}, cand));
		edges.push_back(alt_path({y.first, x.second}, cand));
	} else if(x.first == y.first){
		Path q = alt_path({x.first, -1}, cand);
		edges.push_back(q);
		edges.push_back(alt_path({x.first, q.second.second}, cand));
	} else if(x.second == y.second){
		Path q = alt_path({-1, x.second}, cand);
		edges.push_back(q);
		edges.push_back(alt_path({q.second.first, x.second}, cand));
	}
	sort(edges.begin(), edges.end());
	while(edges.size() > 0 && edges[edges.size() - 1].first >= MAXD) edges.pop_back();
	return edges;
}

OptPaths join(OptPaths a, OptPaths b){
	OptPaths cand;
	for(auto x : a){
		for(auto y : b){
			if(x.second.second != y.second.first){
				cand.push_back({min(x.first + y.first, MAXD), {x.second.first, y.second.second}});
			}
		}
	}
	return cand;
}

OptPaths edge(int id, LL cost){
	OptPaths x;
	x.push_back({cost, {id, id}});
	return x;
}

vector<vector<OptPaths> > cachedpaths;
void compute_paths(int s){
	// start bellman-ford at s
	vector<OptPaths> sssp(n);
	vector<vector<int> > adj(n); // to, id, cost
	for(int i = 0; i < m; i++){
		if(a[i] == s){
			sssp[b[i]] = edge(i, c[i]);
		} else if(b[i] == s){
			sssp[a[i]] = edge(i, c[i]);
		} else {
			adj[a[i]].push_back(i);
			adj[b[i]].push_back(i);
		}
	}
	int vis[n][4];
	for(int i = 0; i < n; i++){
		for(int j = 0; j < 4; j++){
			vis[i][j] = 0;
		}
	}
	set<pair<LL,pair<int,int> > > stuff;
	for(int i = 0; i < n; i++){
		for(int idx = 0; idx < sssp[i].size(); idx++){
			stuff.insert({sssp[i][idx].first, {i, idx}});
			break;
		}
	}
	while(!stuff.empty()){
		pair<LL,pair<int,int> > v = *stuff.begin();
		if(v.first >= MAXD){
			break;
		}
		stuff.erase(stuff.begin());
		vis[v.second.first][v.second.second] = 1;
		if(v.second.second + 1 < sssp[v.second.first].size()){
			stuff.insert({sssp[v.second.first][v.second.second + 1].first, {v.second.first, v.second.second + 1}});
		}
		for(auto i : adj[v.second.first]){
			if(b[i] == v.second.first){
				swap(a[i], b[i]);
			}
			int w = b[i];
			OptPaths e = edge(i, c[i]);
			OptPaths x = join(sssp[a[i]], e);
			x.insert(x.end(), sssp[w].begin(), sssp[w].end());
			for(int idx = 0; idx < sssp[w].size(); idx++){
				if(!vis[w][idx]){
					stuff.erase({sssp[w][idx].first, {w, idx}});
					break;
				}
			}
			sssp[w] = process(x);
			for(int idx = 0; idx < sssp[w].size(); idx++){
				if(!vis[w][idx]){
					stuff.insert({sssp[w][idx].first, {w, idx}});
					break;
				}
			}
		}
	}
	cachedpaths[s] = sssp;
}

void compute_paths2(int s){
	// start bellman-ford at s
	vector<OptPaths> sssp(n);
	for(int id = 0; id < m; id++){
		if(a[id] != s && b[id] != s) continue;
		if(b[id] == s) swap(a[id], b[id]);
		// all paths starting with edge id

		int st = b[id];
		vector<vector<int> > adj(n);
		for(int i = 0; i < m; i++){
			if(a[i] != s && b[i] != s){
				adj[a[i]].push_back(i);
				adj[b[i]].push_back(i);
			}
		}
		int vis[n][2];
		pair<LL,int> dist[n][2];
		for(int i = 0; i < n; i++){
			vis[i][0] = vis[i][1] = 0;
			dist[i][0] = {MAXD, -1};
			dist[i][1] = {MAXD, -2};
		}
		dist[st][0] = {c[id], id};
		dist[st][1] = {MAXD, -1};

		set<pair<LL,pair<int,int> > > stuff;
		for(int i = 0; i < n; i++){
			if(i != s){
				stuff.insert({dist[i][0].first, {i, 0}});
				stuff.insert({dist[i][1].first, {i, 1}});
			}
		}
		while(!stuff.empty()){
			pair<LL,pair<int,int> > x = *stuff.begin();
			stuff.erase(stuff.begin());
			int v = x.second.first;
			int idx = x.second.second;
			vis[v][idx] = 1;
			for(auto i : adj[v]){
				if(b[i] == v){
					swap(a[i], b[i]);
				}
				int w = b[i];
				LL d = 0;
				if(dist[v][0].second != i){
					d = dist[v][0].first + c[i];
				} else {
					d = dist[v][1].first + c[i];
				}
				for(int j = 0; j < 2; j++){
					if(!vis[w][j]){
						stuff.erase({dist[w][j].first,{w,j}});
					}
				}
				if(dist[w][0].second == i){
					dist[w][0].first = min(dist[w][0].first, d);
				} else if(dist[w][1].second == i){
					dist[w][0].first = min(dist[w][0].first, d);
				} else if(d < dist[w][1].first){
					dist[w][1] = {d, i};
				}
				if(dist[w][0] > dist[w][1]) swap(dist[w][0], dist[w][1]);
				for(int j = 0; j < 2; j++){
					if(!vis[w][j]){
						stuff.insert({dist[w][j].first,{w,j}});
					}
				}
			}
		}
		for(int i = 0; i < n; i++){
			if(i == s) continue;
			sssp[i].push_back({dist[i][0].first,{id,dist[i][0].second}});
			sssp[i].push_back({dist[i][1].first,{id,dist[i][1].second}});
		}
	}
	for(int i = 0; i < n; i++){
		if(i == s) continue;
		sssp[i] = process(sssp[i]);
	}
	cachedpaths[s] = sssp;
}


int main(){
	cin.sync_with_stdio(0); cin.tie(0);
	cin >> n >> m >> t >> l;
	cachedpaths.resize(n);
	a.resize(m); b.resize(m); c.resize(m);
	for(int i = 0; i < m; i++){
		cin >> a[i] >> b[i] >> c[i];
		a[i]--; b[i]--;
	}
	vector<int> plan(l);
	vector<int> need(n, 0);
	for(int i = 0; i < l; i++){
		cin >> plan[i];
		plan[i]--;
		need[plan[i]] = 1;
	}
	vector<pair<int,int> > updates(t);
	for(int i = 0; i < t; i++){
		cin >> updates[i].first >> updates[i].second;
		updates[i].first--; updates[i].second--;
		need[updates[i].second] = 1;
	}
	for(int i = 0; i < n; i++){
		compute_paths2(i);
		//cout << "done " << i << endl;
		/*for(int j = 0; j < n; j++){
			cout << "paths from " << i << " to " << j << '\n';
			if(i != j){
				OptPaths x = cachedpaths[i][j];
				for(auto v : x){
					cout << v.second.first << " " << v.second.second << " " << v.first << '\n';
				}
			}
		}*/
	}
	for(int tt = 0; tt < t; tt++){
		plan[updates[tt].first] = updates[tt].second;
		OptPaths route = cachedpaths[plan[0]][plan[1]];
		for(int j = 2; j < l; j++){
			route = process(join(route, cachedpaths[plan[j-1]][plan[j]] ) );
		}
		cout << (route.size() > 0 && route[0].first < MAXD ? route[0].first : -1) << '\n';
	}
}

Compilation message (stderr)

wild_boar.cpp: In function 'OptPaths process(OptPaths)':
wild_boar.cpp:37:19: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
  for(int i = 0; i < cand.size(); i++){
                 ~~^~~~~~~~~~~~~
wild_boar.cpp: In function 'void compute_paths(int)':
wild_boar.cpp:105:24: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
   for(int idx = 0; idx < sssp[i].size(); idx++){
                    ~~~~^~~~~~~~~~~~~~~~
wild_boar.cpp:117:26: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
   if(v.second.second + 1 < sssp[v.second.first].size()){
      ~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
wild_boar.cpp:128:25: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
    for(int idx = 0; idx < sssp[w].size(); idx++){
                     ~~~~^~~~~~~~~~~~~~~~
wild_boar.cpp:135:25: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
    for(int idx = 0; idx < sssp[w].size(); idx++){
                     ~~~~^~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...