Problem:
Planning Railroad Discontinuation
The ICPC Kingdom has a large round lake in its center, and all of its cities are developed around
the lake, forming a circle of cities. Because all of them are developed under the same urban
plan, the cities are made quite similar. They have exactly the same subway networks. Some of
their stations are also stations of inter-city bullet trains connecting two corresponding stations
of adjacent cities. All of the train routes provide two-way traffic between two terminal stations
without any intermediate stations.
The cities have the same number of subway stations and subway routes. In each city, the
stations are numbered sequentially as 0, 1, 2, . . . . Whether two stations in a city are connected
by a subway route depends only on their station numbers and not on the city. If a station v is
connected to a station u in one city, so is in all the other cities. The travel distance between
two stations v and u are the same for all the cities.
All the cities have exactly the same list of station numbers of bullet train stations. If a station
$s$ is a bullet train station in one city, so is in all the other cities. All the pairs of two bullet train
stations of the same station number in two adjacent cities are connected by a bullet train route.
If a station $s$ is one end of a bullet train route, the station $s$ in an adjacent city is the other
end. There exist no other bullet train routes. One can travel between any two stations in the
Kingdom via one or more subway and/or bullet train services.
Due to financial difficulties in recent years, the Kingdom plans to discontinue some of the
subway and bullet train services to reduce the maintenance cost of the railroad system. The
maintenance cost is the sum of maintenance costs of the subway routes and the bullet train
routes. The maintenance cost of a subway route is the sum of base cost depending on the city
and cost proportional to the travel distance of the route. The maintenance cost of a bullet train
route depends only on the two cities connected by the route.
You are asked to make a plan to discontinue some of the routes that minimizes the total main-tenance cost. Of course, all the pairs of the stations in the Kingdom should still be connected
through one or more subway and/or bullet train services after the discontinuation.
Input
The input consists of a single test case of the following format.
$n$ $m$
$v_1$ $u_1$ $d_1$
$\vdots$
$v_m$ $u_m$ $d_m$
$l$
$a_0$ $b_0$
$\vdots$
$a_{l-1}$ $b_{l-1}$
$r$
$s_1$
$\vdots$
$s_r$
Here, $n$ is an integer satisfying $2 \leq n \leq 10^4$, which is the number of the subway stations in a city.
The stations in each city are numbered from $0$ to $n - 1$. $m$ is an integer satisfying $1 \leq m \leq 10^5$,
which is the number of the subway routes in a city. The following $m$ lines are information on
the subway system in a city. The $i$-th of the $m$ lines has three integers $v_i$, $u_i$, and $d_i$, satisfying
$0 \leq v_i \lt n$, $0 \leq u_
...(truncated)

Submitted solutions:

code_snippet: #ifdef NACHIA
#define _GLIBCXX_DEBUG
#else
#define NDEBUG
#endif
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
using ll = long long;
const ll INF = 1ll << 60;
#define REP(i,n) for(ll i=0; i<ll(n); i++)
template <class T> using V = vector<T>;
template <class T> using VV = V<V<T>>;
template <class A, class B> void chmax(A& l, const B& r){ if(l < r) l = r; }
template <class A, class B> void chmin(A& l, const B& r){ if(r < l) l = r; }

struct UnionFind {
    V<int> A;
    UnionFind(int n) : A(n, -1) {}
    int group(int v){
        return A[v] < 0 ? v : A[v] = group(A[v]);
    }
    bool same(int u, int v){ return group(u) == group(v); }
    int merge(int u, int v){
        u = group(u), v = group(v);
        if(u == v) return u;
        A[v] = u;
        return u;
    }
};

struct Segtree {
    int N;
    V<pair<int,int>> A;
    Segtree(int n = 0) : N(1) {
        while(N < n) N *= 2;
        A.assign(N*2, {1001001001,-1});
    }
    void agg(int i){
        A[i] = min(A[i*2], A[i*2+1]);
    }
    Segtree(V<int> a) : Segtree(a.size()) {
        REP(i,a.size()) A[N+i] = {a[i],int(i)};
        for(int i=N-1; i>=1; i--) agg(i);
    }
    auto prod(int l, int r){
        l += N; r += N;
        auto ans = A[0];
        while(l < r){
            if(l%2) ans = min(ans, A[l++]);
            if(r%2) ans = min(ans, A[--r]);
            l /= 2, r /= 2;
        }
        return ans;
    }
};

struct Edge { int u,v,d; };

void testcase(){
    int N, M; cin >> N >> M;
    V<Edge> edges(M);
    for(auto& [u,v,d] : edges) cin >> u >> v >> d;
    sort(edges.begin(), edges.end(), [&](auto l, auto r){ return l.d < r.d; });
    ll L; cin >> L;
    V<int> A(L), B(L);
    REP(i,L) cin >> A[i] >> B[i];
    {
        int maxpos = max_element(A.begin(), A.end()) - A.begin();
        rotate(A.begin(), A.begin() + maxpos + 1, A.end());
        rotate(B.begin(), B.begin() + maxpos + 1, B.end());
    }
    //for(auto a : A) cout << a << " ";
    //cout << endl;
    //for(auto a : B) cout << a << " ";
    //cout << endl;
    auto An = A; for(auto& a : An) a = -a;
    Segtree ds(An);
    Segtree dsB(B);
    V<int> X;
    auto dfs = [&](auto& dfs, int l, int r) -> void {
        if(l == r) return;
        int m = ds.prod(l, r).second;
        dfs(dfs, l, m);
        dfs(dfs, m+1, r);
        int bl = dsB.prod(l, m+1).first;
        int br = dsB.prod(m+1, r+1).first;
        X.push_back(A[m] - max(bl, br));
    };
    dfs(dfs, 0, L-1);
    UnionFind dsu(N);
    V<int> C, wt(N);

    ll ans = 0;
    REP(i,L-1) ans += A[i];
    for(auto a : B) ans += (ll)a * (N-1);

    ll R; cin >> R;
    REP(i,R){ ll s; cin >> s; wt[s] = 1; }
    for(auto [u,v,d] : edges) if(!dsu.same(u,v)){
        u = dsu.group(u);
        v = dsu.group(v);
        ans += ll(d) * L;
        if(wt[u] >= 1 && wt[v] >= 1) C.push_back(d);
        wt[dsu.merge(u,v)] = wt[u] + wt[v];
    }
    
    //for(auto a : C) cout << a << " ";
    //cout << endl;
    //for(auto a : X) cout << a << " ";
    //cout << endl;

    V<ll> sumC(C.size() + 1);
    for(ll i=(ll)C.size()-1; i>=0; i--) sumC[i] = sumC[i+1] + C[i];

    for(auto x : X){
        ll pos = lower_bound(C.begin(), C.end(), x) - C.begin();
        ll cnt = C.size() - pos;
        ans -= sumC[pos];
        ans += x * cnt;
    }

    cout << ans << "\n";
}

int main(){
    cin.tie(0)->sync_with_stdio(0);
    testcase();
    return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 18108
final_rank: 2

code_snippet: #include <bits/stdc++.h>
#define fi first
#define se second
using namespace std;
using ll=long long;
using ull=unsigned long long;
using db=long double;
using pii=pair<int,int>;
using pll=pair<ll,ll>;
using pdb=pair<db,db>;
using tii=tuple<int,int,int>;
using tdb=tuple<db,db,db>;
using tll=tuple<ll,ll,ll>;
using ti4=tuple<int,int,int,int>;
using tl4=tuple<ll,ll,ll,ll>;
using td4=tuple<db,db,db,db>;
const ll inf=1e18;
const int N=3e5+5,M=20;
int n,m,k,l,a[N],b[N],in[N];
pii arr[N];
tii e[N];
int t,wT[N];
ll sT[N],cT[N];
ll sum,ans;
struct UF{
	int p[N],dat[N];
	void init(int n,int val[]){
		for(int i=1;i<=n;i++){
			p[i]=0;
			dat[i]=val[i];
		}
	}
	int Find(int x){
		if(!p[x]) return x;
		return p[x]=Find(p[x]);
	}
	template<class F>
	bool Union(int x,int y,F f){
		x=Find(x);
		y=Find(y);
		if(x==y) return false;
		p[y]=x;
		dat[x]=f(dat[x],dat[y]);
		return true;
	}
}UT,UG;
int main(){
	ios::sync_with_stdio(false); cin.tie(0);
	cin>>n>>m;
	for(int u,v,w,i=1;i<=m;i++){
		cin>>u>>v>>w;
		u++;
		v++;
		e[i]=tii(w,u,v);
	}
	cin>>k;
	for(int i=1;i<=k;i++){
		cin>>a[i]>>b[i];
		arr[i]=pii(a[i],i);
		sum+=b[i];
	}
	{
		cin>>l;
		for(int u,i=1;i<=l;i++){
			cin>>u;
			in[u+1]=1;
		}
		auto mrg=[&](int x,int y){
			return x|y;
		};
		UT.init(n,in);
		sort(e+1,e+1+m);
		wT[++t]=-2e9;
		cT[t]=l;
		for(int i=1;i<=m;i++){
			int u=get<1>(e[i]),v=get<2>(e[i]),w=get<0>(e[i]);
			int con1=UT.dat[UT.Find(u)],con2=UT.dat[UT.Find(v)];
			if(!UT.Union(u,v,mrg)) continue;
			if(i==1||wT[t]<w){
				wT[++t]=w;
				sT[t]=sT[t-1];
				cT[t]=cT[t-1];
			}
			if(!con1||!con2){
				ans+=1ll*k*w+sum;
			} else{
				sT[t]+=w;
				cT[t]--;
			}
		}
	}
	{
		UG.init(k,b);
		auto mrg=[&](int x,int y){
			return min(x,y);
		};
		sort(arr+1,arr+1+k);
		for(int p=1;p<k;p++){
			int i=UG.Find(arr[p].se),j=UG.Find(arr[p].se==k?1:arr[p].se+1);
			int w=arr[p].fi-max(UG.dat[i],UG.dat[j]);
			int idx=upper_bound(wT+1,wT+1+t,w)-wT-1;
			ans+=1ll*cT[idx]*arr[p].fi;
			ans+=sT[idx]+1ll*(l-cT[idx])*max(UG.dat[i],UG.dat[j]);
			UG.Union(i,j,mrg);
		}
		ans+=sT[t]+1ll*(l-1)*UG.dat[UG.Find(1)];
	}
	cout<<ans<<endl;
	return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 20976
final_rank: 1

code_snippet: #include <algorithm>
#include <cassert>
#include <climits>
#include <cmath>
#include <iostream>
#include <iterator>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include <random>
#include <complex>
#include <bitset>
#include <iomanip>
#include <memory>
#include <functional>
#include <stack>
#include <limits>

#define rep(i, n, s) for (int i = (s); i < int(n); i++)
#define per(i, n, s) for (int i = (n) - 1; i >= int(s); i--)
#define MM << " " <<
#define all(x) begin(x), end(x)
#define rall(x) rbegin(x), rend(x)

template <class T>
using MinHeap = std::priority_queue<T, std::vector<T>, std::greater<T>>;
template <class T>
using MaxHeap = std::priority_queue<T>;

using ll = long long;
using Pii = std::pair<int, int>;
using Pll = std::pair<ll, ll>;
using Pdd = std::pair<double, double>;

template <class T>
bool chmin(T &a, const T b) {
    if (b < a) {
        a = b;
        return true;
    } else {
        return false;
    }
}

template <class T>
bool chmax(T &a, const T b) {
    if (a < b) {
        a = b;
        return true;
    } else {
        return false;
    }
}

template <class T>
void vdeb(const std::vector<T> &da) {
    auto n = da.size();
    for (size_t i = 0; i < n; i++) {
        if (i == n - 1)
            std::cout << da[i];
        else
            std::cout << da[i] << " ";
    }
    std::cout << std::endl;
}
template<class T>
void vdeb(const std::vector<std::vector<T>> &da) {
    auto n = da.size();
    for (size_t i = 0; i < n; i++) {
        // std::cout << i << " : ";
        vdeb(da[i]);
    }
    std::cout << std::endl;
}


class UnionFind {
    int _n;
    int _size;
    std::vector<int> par_size;

    public:
    UnionFind() :_n(0), _size(0){}
    UnionFind(int n) : _n(n), _size(n), par_size(n, -1) {}

    int unite(int a, int b) {
        assert(0 <= a && a < _n);
        assert(0 <= b && b < _n);
        a = root(a), b = root(b);
        if(a == b) return a;
        _size--;
        if(-par_size[a] < -par_size[b]) {
            par_size[b] += par_size[a];
            return par_size[a] = b;
        }
        else {
            par_size[a] += par_size[b];
            return par_size[b] = a;
        }
    }

    int root(int a) {
        assert(0 <= a && a < _n);
        if(par_size[a] < 0) return a;
        return par_size[a] = root(par_size[a]); 
    }

    bool same(int a, int b) {
        assert(0 <= a && a < _n);
        assert(0 <= b && b < _n);
        return root(a) == root(b);
    }

    int size(int a) {
        assert(0 <= a && a< _n);
        return -par_size[root(a)];
    }

    int size() {return _size;}

    std::vector<std::vector<int>> groups() {
        std::vector<int> leader_buf(_n), group_size(_n);
        for (int i = 0; i < _n; i++) {
            leader_buf[i] = root(i);
            group_size[leader_buf[i]]++;
        }
        std::vector<std::vector<int>> result(_n);
        for (int i = 0; i < _n; i++) {
            result[i].reserve(group_size[i]);
        }
        for (int i = 0; i < _n; i++) {
            result[leader_buf[i]].push_back(i);
        }
        result.erase(
            std::remove_if(result.begin(), result.end(),
                           [&](const std::vector<int>& v) { return v.empty(); }),
            result.end());
        return result;
    }
};

using namespace std;

int main() {
    int n, m; cin >> n >> m;
    vector<pair<ll, Pii>> ed(m);
    for(auto &i : ed) cin >> i.second.first >> i.second.second >> i.first;
    int l; cin >> l;
    vector<pair<ll, Pii>> cd(l);
    vector<ll> base(l);
    rep(i,l,0) {
        cin >> cd[i].first;
        cin >> base[i];
        cd[i].second = {i, (i+1)%l};
    }
    int r; cin >> r;
    vector<int> s(n);
    rep(i,r,0) {
        int x; cin >> x;
        s[x] = 1;
    }
    sort(all(ed));
    UnionFind ufg(n);
    ll ans = 0, base_sum = accumulate(all(base),0LL);
    vector<ll> weight, num = {r}, cost = {0};
    // vdeb(s);
    for(auto &i :ed) {
        int a = i.second.first, b = i.second.second;
        a = ufg.root(a);
        b = ufg.root(b);
        if(ufg.same(a, b)) continue;
        ufg.unite(a, b);
        int c = ufg.root(a);
        if(s[a] & s[b]) {
            weight.emplace_back(i.first);
            num.emplace_back(num.back() - 1);
            cost.emplace_back(cost.back() + i.first);
        }
        else {
            ans += i.first * l + base_sum;
        }
        s[c] = s[a] | s[b];
    }
    // vdeb(weight);
    // cerr << ans << endl;
    UnionFind ufc(l);
    vector<int> snap(l);
    sort(all(cd));
    for(auto &i : cd) {
        int a = ufc.root(i.second.first);
        int b = ufc.root(i.second.second);
        if(a == b) continue;
        {
            int g = a;
            auto itr = lower_bound(all(weight), i.first - base[g]);
            int id = itr - begin(weight);
            ans += cost[id] - cost[snap[g]];
            ans += base[g] * (id - snap[g]);
            snap[g] = id;
        }
        {
            int g = b;
            auto itr = lower_bound(all(weight), i.first - base[g]);
            int id = itr - begin(weight);
            ans += cost[id] - cost[snap[g]];
            ans += base[g] * (id - snap[g]);
            snap[g] = id;
        }
        ufc.unite(a, b);
        ans += num[min(snap[a], snap[b])] * i.first;
        int c = ufc.root(a);
        snap[c] = max(snap[a], snap[b]);
        base[c] = min(base[a], base[b]);
        // cout << ans MM i.first MM i.second.first MM i.second.second << endl;
        // vdeb(snap);
    }
    int las = ufc.root(0);
    // vdeb(cost);
    // cerr << las << endl;
    ans += cost.back() - cost[snap[las]] + base[las] * (cost.size() - snap[las] - 1);
    cout << ans << endl;
}
accuracy: 1
time_ms: 110
memory_kb: 8204
final_rank: 5

code_snippet: #ifndef LOCAL
#pragma GCC optimize ("Ofast")
#pragma GCC optimize ("unroll-loops")
#endif

#include <bits/stdc++.h>
using namespace std;

using ll=long long;
#define int ll

#define rng(i,a,b) for(int i=int(a);i<int(b);i++)
#define rep(i,b) rng(i,0,b)
#define gnr(i,a,b) for(int i=int(b)-1;i>=int(a);i--)
#define per(i,b) gnr(i,0,b)
#define pb push_back
#define eb emplace_back
#define a first
#define b second
#define bg begin()
#define ed end()
#define all(x) x.bg,x.ed
#define si(x) int(x.size())
#ifdef LOCAL
#define dmp(x) cerr<<__LINE__<<" "<<#x<<" "<<x<<endl
#else
#define dmp(x) void(0)
#endif

template<class t,class u> bool chmax(t&a,u b){if(a<b){a=b;return true;}else return false;}
template<class t,class u> bool chmin(t&a,u b){if(b<a){a=b;return true;}else return false;}

template<class t> using vc=vector<t>;
template<class t> using vvc=vc<vc<t>>;

using pi=pair<int,int>;
using vi=vc<int>;

template<class t,class u>
ostream& operator<<(ostream& os,const pair<t,u>& p){
	return os<<"{"<<p.a<<","<<p.b<<"}";
}

template<class t> ostream& operator<<(ostream& os,const vc<t>& v){
	os<<"{";
	for(auto e:v)os<<e<<",";
	return os<<"}";
}

#define mp make_pair
#define mt make_tuple
#define one(x) memset(x,-1,sizeof(x))
#define zero(x) memset(x,0,sizeof(x))
#ifdef LOCAL
void dmpr(ostream&os){os<<endl;}
template<class T,class... Args>
void dmpr(ostream&os,const T&t,const Args&... args){
	os<<t<<" ";
	dmpr(os,args...);
}
#define dmp2(...) dmpr(cerr,__LINE__,##__VA_ARGS__)
#else
#define dmp2(...) void(0)
#endif

using uint=unsigned;
using ull=unsigned long long;

template<class t,size_t n>
ostream& operator<<(ostream&os,const array<t,n>&a){
	return os<<vc<t>(all(a));
}

template<int i,class T>
void print_tuple(ostream&,const T&){
}

template<int i,class T,class H,class ...Args>
void print_tuple(ostream&os,const T&t){
	if(i)os<<",";
	os<<get<i>(t);
	print_tuple<i+1,T,Args...>(os,t);
}

template<class ...Args>
ostream& operator<<(ostream&os,const tuple<Args...>&t){
	os<<"{";
	print_tuple<0,tuple<Args...>,Args...>(os,t);
	return os<<"}";
}

template<class t>
void print(t x,int suc=1){
	cout<<x;
	if(suc==1)
		cout<<"\n";
	if(suc==2)
		cout<<" ";
}

ll read(){
	ll i;
	cin>>i;
	return i;
}

vi readvi(int n,int off=0){
	vi v(n);
	rep(i,n)v[i]=read()+off;
	return v;
}

pi readpi(int off=0){
	int a,b;cin>>a>>b;
	return pi(a+off,b+off);
}

template<class t,class u>
void print(const pair<t,u>&p,int suc=1){
	print(p.a,2);
	print(p.b,suc);
}

template<class T>
void print(const vector<T>&v,int suc=1){
	rep(i,v.size())
		print(v[i],i==int(v.size())-1?suc:2);
}

template<class T>
void print_offset(const vector<T>&v,ll off,int suc=1){
	rep(i,v.size())
		print(v[i]+off,i==int(v.size())-1?suc:2);
}

template<class T,size_t N>
void print(const array<T,N>&v,int suc=1){
	rep(i,N)
		print(v[i],i==int(N)-1?suc:2);
}

string readString(){
	string s;
	cin>>s;
	return s;
}

template<class T>
T sq(const T& t){
	return t*t;
}

//#define CAPITAL
void yes(bool ex=true){
	#ifdef CAPITAL
	cout<<"YES"<<"\n";
	#else
	cout<<"Yes"<<"\n";
	#endif
	if(ex)exit(0);
	#ifdef LOCAL
	cout.flush();
	#endif
}
void no(bool ex=true){
	#ifdef CAPITAL
	cout<<"NO"<<"\n";
	#else
	cout<<"No"<<"\n";
	#endif
	if(ex)exit(0);
	#ifdef LOCAL
	cout.flush();
	#endif
}
void possible(bool ex=true){
	#ifdef CAPITAL
	cout<<"POSSIBLE"<<"\n";
	#else
	cout<<"Possible"<<"\n";
	#endif
	if(ex)exit(0);
	#ifdef LOCAL
	cout.flush();
	#endif
}
void impossible(bool ex=true){
	#ifdef CAPITAL
	cout<<"IMPOSSIBLE"<<"\n";
	#else
	cout<<"Impossible"<<"\n";
	#endif
	if(ex)exit(0);
	#ifdef LOCAL
	cout.flush();
	#endif
}

constexpr ll ten(int n){
	return n==0?1:ten(n-1)*10;
}

const ll infLL=LLONG_MAX/3;

#ifdef int
const int inf=infLL;
#else
const int inf=INT_MAX/2-100;
#endif

int topbit(signed t){
	return t==0?-1:31-__builtin_clz(t);
}
int topbit(ll t){
	return t==0?-1:63-__builtin_clzll(t);
}
int botbit(signed a){
	return a==0?32:__builtin_ctz(a);
}
int botbit(ll a){
	return a==0?64:__builtin_ctzll(a);
}
int popcount(signed t){
	return __builtin_popcount(t);
}
int popcount(ll t){
	return __builtin_popcountll(t);
}
bool ispow2(int i){
	return i&&(i&-i)==i;
}
ll mask(int i){
	return (ll(1)<<i)-1;
}

bool inc(int a,int b,int c){
	return a<=b&&b<=c;
}

template<class t> void mkuni(vc<t>&v){
	sort(all(v));
	v.erase(unique(all(v)),v.ed);
}

ll rand_int(ll l, ll r) { //[l, r]
	#ifdef LOCAL
	static mt19937_64 gen;
	#else
	static mt19937_64 gen(chrono::steady_clock::now().time_since_epoch().count());
	#endif
	return uniform_int_distribution<ll>(l, r)(gen);
}

template<class t>
void myshuffle(vc<t>&a){
	rep(i,si(a))swap(a[i],a[rand_int(0,i)]);
}

template<class t>
int lwb(const vc<t>&v,const t&a){
	return lower_bound(all(v),a)-v.bg;
}

vvc<int> readGraph(int n,int m){
	vvc<int> g(n);
	rep(i,m){
		int a,b;
		cin>>a>>b;
		//sc.read(a,b);
		a--;b--;
		g[a].pb(b);
		g[b].pb(a);
	}
	return g;
}

vvc<int> readTree(int n){
	return readGraph(n,n-1);
}

//VERIFY: yosupo
//KUPC2017J
//AOJDSL1A
//without rank
struct unionfind{
	vi p,s;
	int c;
	unionfind(int n):p(n,-1),s(n,1),c(n){}
	int find(int a){
		return p[a]==-1?a:(p[a]=find(p[a]));
	}
	//set b to a child of a
	bool unite(int a,int b){
		a=find(a);
		b=find(b);
		if(a==b)return false;
		p[b]=a;
		s[a]+=s[b];
		c--;
		return true;
	}
	bool same(int a,int b){
		return find(a)==find(b);
	}
	int sz(int a){
		return s[find(a)];
	}
};

//max cartesian tree
vi cartesiantree(const vi&a){
	int n=si(a);
	vi par(n,-1);
	vi s;
	rep(i,n){
		int last=-1;
		while(si(s)&&a[s.back()]<=a[i]){
			last=s.back();
			s.pop_back();
		}
		if(last!=-1)par[last]=i;
		if(si(s))par[i]=s.back();
		s.pb(i);
	}
	return par;
}

void slv(){
	int vs;cin>>vs;
	using T=tuple<int,int,int>;
	vc<T> es;
	{
		int m;cin>>m;
		rep(i,m){
			int a,b,c;cin>>a>>b>>c;
			es.eb(c,a,b);
		}
	}
	
	int n;cin>>n;
	vi adj(n),base(n);
	rep(i,n)cin>>adj[i]>>base[i];
	{
		int f=max_element(all(adj))-adj.bg;
		rotate(adj.bg,adj.bg+f+1,adj.ed);
		rotate(base.bg,base.bg+f+1,base.ed);
		adj.pop_back();
	}
	
	int ans=0;
	vi cs;
	{
		int tot=accumulate(all(base),int(0));
		vi has(vs);
		{
			int r;cin>>r;
			rep(_,r){
				int v;cin>>v;
				has[v]=true;
			}
		}
		sort(all(es));
		unionfind uf(vs);
		for(auto [c,a,b]:es){
			a=uf.find(a);
			b=uf.find(b);
			if(uf.unite(a,b)){
				if(has[a]&&has[b]){
					cs.pb(c);
				}else{
					ans+=tot+c*n;
				}
				has[a]|=has[b];
			}
		}
	}
	dmp(ans);
	dmp(cs);
	dmp(adj);
	dmp(base);
	
	vs=si(cs)+1;
	vi sum(vs);
	rep(i,vs-1)sum[i+1]=sum[i]+cs[i];
	
	using A=array<int,2>;
	vc<A> t(n-1,A{-1,-1});
	vi par=cartesiantree(adj);
	int root=-1;
	rep(i,n-1)if(par[i]==-1)root=i;
	else t[par[i]][par[i]<i]=i;

	auto upd=[&](int b,int l,int r){
		l=lwb(cs,l-b);
		r=lwb(cs,r-b);
		ans+=(sum[r]-sum[l])+(r-l)*b;
	};
	auto dfs=[&](auto self,int v)->pi{
		pi lf,rt;
		if(t[v][0]==-1){
			lf=pi(base[v],-inf);
		}else{
			lf=self(self,t[v][0]);
		}
		if(t[v][1]==-1){
			rt=pi(base[v+1],-inf);
		}else{
			rt=self(self,t[v][1]);
		}
		upd(lf.a,lf.b,adj[v]);
		upd(rt.a,rt.b,adj[v]);
		int cut=max(lf.a,rt.a);
		int pos=lwb(cs,adj[v]-cut);
		ans+=(vs-pos)*adj[v];
		return pi(min(lf.a,rt.a),adj[v]);
	};
	
	/*{
		int s=vs*n;
		vc<T> z;
		rep(i,n-1){
			rep(j,vs){
				z.eb(adj[i],i*vs+j,(i+1)*vs+j);
			}
		}
		rep(i,n){
			rep(j,vs-1){
				z.eb(cs[j]+base[i],i*vs+j,i*vs+j+1);
			}
		}
		sort(all(z));
		unionfind uf(s);
		int tmp=0;
		for(auto [c,a,b]:z){
			if(uf.unite(a,b)){
				tmp+=c;
			}
		}
		assert(uf.c==1);
		dmp(tmp);
	}*/
	
	pi z=dfs(dfs,root);
	upd(z.a,z.b,inf);
	print(ans);
}

signed main(){
	cin.tie(0);
	ios::sync_with_stdio(0);
	cout<<fixed<<setprecision(20);
	
	//int t;cin>>t;rep(_,t)
	slv();
}
accuracy: 1
time_ms: 40
memory_kb: 25188
final_rank: 4

code_snippet: //Let's join Kaede Takagaki Fan Club !!
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <cassert>
#include <string>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <functional>
#include <iostream>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <cassert>
#include <iomanip>
#include <chrono>
#include <random>
#include <bitset>
#include <complex>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
#define int long long
//#define L __int128
typedef long long ll;
typedef pair<int,int> P;
typedef pair<int,P> P1;
typedef pair<P,P> P2;
#define pu push
#define pb push_back
#define eb emplace_back
#define mp make_pair
#define eps 1e-7
#define INF 1000000000
#define a first
#define b second
#define fi first
#define sc second
//#define rng(i,a,b) for(int i=(int)(a);i<(int)(b);i++)
#define rep(i,x) for(int i=0;i<x;i++)
#define repn(i,x) for(int i=1;i<=x;i++)
#define SORT(x) sort(x.begin(),x.end())
#define ERASE(x) x.erase(unique(x.begin(),x.end()),x.end())
#define POSL(x,v) (lower_bound(x.begin(),x.end(),v)-x.begin())
#define POSU(x,v) (upper_bound(x.begin(),x.end(),v)-x.begin())
#define all(x) x.begin(),x.end()
#define si(x) int(x.size())
#define pcnt(x) __builtin_popcountll(x)

#ifdef LOCAL
#define dmp(x) cerr<<__LINE__<<" "<<#x<<" "<<x<<endl
#else
#define dmp(x) void(0)
#endif
 
template<class t,class u> bool chmax(t&a,u b){if(a<b){a=b;return true;}else return false;}
template<class t,class u> bool chmin(t&a,u b){if(b<a){a=b;return true;}else return false;}
 
template<class t> using vc=vector<t>;
 
template<class t,class u>
ostream& operator<<(ostream& os,const pair<t,u>& p){
	return os<<"{"<<p.fi<<","<<p.sc<<"}";
}
 
template<class t> ostream& operator<<(ostream& os,const vc<t>& v){
	os<<"{";
	for(auto e:v)os<<e<<",";
	return os<<"}";
}
 
 //https://codeforces.com/blog/entry/62393
struct custom_hash {
	static uint64_t splitmix64(uint64_t x) {
		// http://xorshift.di.unimi.it/splitmix64.c
		x += 0x9e3779b97f4a7c15;
		x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
		x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
		return x ^ (x >> 31);
	}
 
	size_t operator()(uint64_t x) const {
		static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
		return splitmix64(x + FIXED_RANDOM);
	}
	//don't make x negative!
	size_t operator()(pair<int,int> x)const{
		return operator()(uint64_t(x.first)<<32|x.second);
	}
};
//unordered_set -> dtype, null_type
//unordered_map -> dtype(key), dtype(value)
using namespace __gnu_pbds;
template<class t,class u>
using hash_table=gp_hash_table<t,u,custom_hash>;

template<class T>
void g(T &a){
	cin >> a;
}
template<class T>
void o(const T &a,bool space=false){
	cout << a << (space?' ':'\n');
}
//ios::sync_with_stdio(false);
const ll mod = 998244353;
//const ll mod = 1000000007;
mt19937_64 mt(chrono::steady_clock::now().time_since_epoch().count());
template<class T>
void add(T&a,T b){
	a+=b;
	if(a >= mod) a-=mod;
}
ll modpow(ll x,ll n){
	ll res=1;
	while(n>0){
		if(n&1) res=res*x%mod;
		x=x*x%mod;
		n>>=1;
	}
	return res;
}
#define _sz 1
ll F[_sz],R[_sz];
void make(){
	F[0] = 1;
	for(int i=1;i<_sz;i++) F[i] = F[i-1]*i%mod;
	R[_sz-1] = modpow(F[_sz-1], mod-2);
	for(int i=_sz-2;i>=0;i--) R[i] = R[i+1] * (i+1) % mod;
}
ll C(int a,int b){
	if(b < 0 || a < b) return 0;
	return F[a]*R[b]%mod*R[a-b]%mod;
}
#define sz 100005
int n, m, c, r, a[sz], b[sz];
vc<P1>edge;
int _bu[sz], _ba[sz], bu[sz], ba[sz];
int T, con_time[sz], con_cnt[sz], con_sum[sz];

vc<int>s;
bool imp[sz];
int par[sz],ran[sz],len[sz],base_sum[sz],base_min[sz],cnt[sz];
vc<int>mem[sz];
void init(){ 
	for(int i=0;i<sz;i++){
		par[i] = i, ran[i] = 1, len[i]=1, base_sum[i]=ba[i], cnt[i]=imp[i];
		base_min[i] = (1<=i and i<=c)?ba[i]:1e18;
		mem[i].clear();
		mem[i].eb(i);
	}
}
int find(int x){ if(x == par[x]) return x; else return par[x] = find(par[x]); }
void unite(int x,int y){
	x = find(x); y = find(y); if(x==y) return;
	if(ran[x] > ran[y]) swap(x, y);
	
	{
		par[x] = y;
		len[y]+=len[x];
		base_sum[y]+=base_sum[x];
		chmin(base_min[y], base_min[x]);
		cnt[y]+=cnt[x];
		for(auto me:mem[x]){
			mem[y].eb(me);
		}
		mem[x].clear();
		ran[y]+=ran[x];
	}
}
bool same(int x,int y){ return find(x)==find(y); }

void solve(){
	cin>>n>>m;
	rep(i,m){
		int u,v,w;cin>>u>>v>>w;
		u++; v++;
		edge.eb(w, mp(u, v));
	}
	cin>>c;
	P mx = mp(-1, -1);
	rep(i, c) {
		cin >> _bu[i] >> _ba[i];
		chmax(mx, mp(_bu[i], i));
	}
	vc<P>adj;
	rep(i, c){
		bu[i+1] = _bu[(i+mx.b+1)%c];
		ba[i+1] = _ba[(i+mx.b+1)%c];
		if(i != c-1) adj.eb(bu[i+1], i+1);
	}
	cin >> r;
	rep(i, r){
		int ss; cin >> ss;
		ss ++;
		s.pb(ss);//cout<<ss<<endl;
		imp[ss] = 1;
	}
	init();
	SORT(edge);
	//o(edge);
	con_time[0] = -1e18;
	T = 1;
	int now_cnt = 0, now_sum = 0;
	
	int spanning = 0;
	rep(i, edge.size()){
		int cs = edge[i].a;
		int j = i;
		while(j < edge.size() and cs == edge[j].a){
			int u = edge[j].b.a;
			int v = edge[j].b.b;
			//cout<<j<<" "<<u<<" "<<v<<endl;
			if(!same(u, v)){
			//cout<<" "<<u<<" "<<find(u)<<" "
			//<<v<<" "<<find(v)<<endl;
			//cout<<cnt[find(u)]<<" "<<cnt[find(v)]<<endl;
				if(cnt[find(u)] == 0 or cnt[find(v)] == 0){
					unite(u, v);
				}
				else{
					now_cnt ++;
					now_sum += cs;
					//cout<<u<<" "<<v<<" "<<j<<" "<<mem[find(u)]<<
					//" "<<mem[find(v)]<<endl;
					unite(u, v);
				}
				spanning += cs;
			}
			j++;
		}
		con_time[T] = cs;
		con_cnt[T] = now_cnt;
		con_sum[T] = now_sum;
		T ++;
		i = j-1;
	}
	repn(i, c){
		//cout << bu[i] << " " << ba[i] << endl;
	}
	con_time[T] = 1e18;
	con_cnt[T] = con_cnt[T-1];
	con_sum[T] = con_sum[T-1];
	T++;
	
	rep(i, T){
		//cout << con_time[i] << " " << con_cnt[i] << " " << con_sum[i] << endl;
	}
	
	SORT(adj);
	int ans = spanning * c;
	repn(i, c) ans += (n-1)*ba[i];
	init();
	//cout<<ans<<endl;
	
	for(auto aa:adj){
		int cs = aa.a;
		int pos = aa.b;
		//pos and pos+1
		//cout<<cs-base_min[find(pos)]<<endl;
		int nowa = upper_bound(con_time, con_time+T, cs-base_min[find(pos)]) - con_time;
		nowa --;
		//cout<<cs-base_min[find(pos+1)]<<endl;
		int nowb = upper_bound(con_time, con_time+T, cs-base_min[find(pos+1)]) - con_time;
		nowb --;
		//cout<<nowa<<" "<<nowb<<endl;
		
		int a = con_cnt[nowa], asum = con_sum[nowa];
		int b = con_cnt[nowb], bsum = con_sum[nowb];
		//cout<<mp(a,asum)<<" "<<mp(b,bsum)<<endl;
		//cout<<r<<" "<<a<<" "<<b<<" "<<cs<<endl;
		ans += (r-min(a,b)) * cs;
		//cout<<"BU"<<(r-min(a,b))*cs<<endl;
		int mx = max(base_min[find(pos)], base_min[find(pos+1)]);
		//cout<<mx<<endl;
		ans -= (con_sum[T-1]-max(asum, bsum)) + (con_cnt[T-1]-max(a,b))*mx;
		//cout<<"ER"<<(con_sum[T-1]-max(asum, bsum)) + (con_cnt[T-1]-max(a,b))*mx<<endl;
		if(a < b){
			ans -= (bsum-asum);// * len[find(pos)];
			ans -= (b-a) * base_min[find(pos)];
		}
		else if(a > b){
			ans -= (asum-bsum);// * len[find(pos+1)];
			ans -= (a-b) * base_min[find(pos+1)];
		}
		unite(pos, pos+1);
	}
	
	o(ans);
}
signed main(){
	cin.tie(0);
	ios::sync_with_stdio(0);
	cout<<fixed<<setprecision(20);
	int t; t = 1; //cin >> t;
	while(t--) solve();
}
accuracy: 1
time_ms: 60
memory_kb: 30956
final_rank: 6

code_snippet: #include <iostream>
#include <unordered_map>
#include <unordered_set>
#include <set>
#include <vector>
#include <numeric>
#include <algorithm>
#include <queue>
#include <string>
#include <random>
#include <array>
#include <climits>
#include <map>
#include <cassert>
#include <stack>
#include <iomanip>
#include <cfloat>
#include <bitset>
#include <fstream>
#include <chrono>

class UnionFind {
	std::vector<int> vec;
public:
	UnionFind(const int size) : vec(size, -1) {};
	int find(const int a) {
		if (vec[a] < 0) {
			return a;
		}
		return vec[a] = find(vec[a]);
	}
	void unite(int a, int b) {
		a = find(a);
		b = find(b);
		if (a == b) return;
		if (vec[a] > vec[b]) std::swap(a, b);
		vec[a] += vec[b];
		vec[b] = a;
	}
	bool same(const int a, const int b) {
		return find(a) == find(b);
	}
};
long long int solve(const int subway_size, const std::vector<std::tuple<int, int, int>> subway_edges, const std::vector<std::pair<int, int>> cities, const std::vector<int> bullet);
int main() {
	int n, m; std::cin >> n >> m;
	std::vector<std::tuple<int, int, int>> subway_edges(m);
	for (auto& [u, v, d] : subway_edges) {
		std::cin >> u >> v >> d;
	}
	std::sort(subway_edges.begin(), subway_edges.end(), [](const auto a, const auto b) {return std::get<2>(a) < std::get<2>(b); });
	int l; std::cin >> l;
	std::vector<std::pair<int, int>> cities(l);
	for (auto& [a, b] : cities) {
		std::cin >> a >> b;
	}
	int r; std::cin >> r;
	std::vector<int> bullet(r);
	for (auto& s : bullet) {
		std::cin >> s;
	}
	std::vector<std::tuple<int, int, int>> subway_tree_edges;
	UnionFind uft(n);
	for (const auto [u, v, d] : subway_edges) {
		if (uft.same(u, v)) continue;
		uft.unite(u, v);
		subway_tree_edges.emplace_back(u, v, d);
	}
	const auto result = solve(n, subway_tree_edges, cities, bullet);
	std::cout << result << '\n';
}
std::vector<long long int> merge_timming(const int subway_size, const std::vector<std::tuple<int, int, int>> &edges, const std::vector<int> &bullet) {
	std::vector<long long int> result;
	std::vector<bool> has_bullet_station(subway_size, 0);
	for (const auto b : bullet) {
		has_bullet_station[b] = true;
	}
	UnionFind uft(subway_size);
	for (const auto [u, v, d] : edges) {
		const auto a = uft.find(u);
		const auto b = uft.find(v);
		if (has_bullet_station[a] && has_bullet_station[b]) {
			result.push_back(d);
		}
		uft.unite(a, b);
		const auto c = uft.find(a);
		has_bullet_station[c] = has_bullet_station[a] || has_bullet_station[b];
	}
	return result;
}
long long int all_need(const int subway_size, const std::vector<std::tuple<int, int, int>>& edges, const std::vector<int>& bullet) {
	UnionFind uft(subway_size);
	long long int result{ 0 };
	for (const auto b : bullet) {
		uft.unite(bullet.front(), b);
	}
	for (const auto [u, v, d] : edges) {
		if (uft.same(u, v)) continue;
		uft.unite(u, v);
		result += d;
	}
	return result;
}
long long int solve(const int subway_size, const std::vector<std::tuple<int, int, int>> subway_tree_edges, const std::vector<std::pair<int, int>> cities, const std::vector<int> bullet) {

	std::vector<int> min_city_base; std::transform(cities.begin(), cities.end(), std::back_inserter(min_city_base), [](const auto a) {return a.second; });
	UnionFind uft(cities.size());
	std::vector<int> sorted_by_bullet_cost(cities.size()); std::iota(sorted_by_bullet_cost.begin(), sorted_by_bullet_cost.end(), 0);
	std::sort(sorted_by_bullet_cost.begin(), sorted_by_bullet_cost.end(), [&cities](const int i, const int j) {return cities[i].first < cities[j].first; });
	sorted_by_bullet_cost.pop_back();
	const auto merge = merge_timming(subway_size, subway_tree_edges, bullet);
	std::vector<long long int> merge_sum{ 0 }; std::partial_sum(merge.begin(), merge.end(), std::back_inserter(merge_sum));
	long long int result{ 0 };
	for (const auto i : sorted_by_bullet_cost) {
		const auto j = (i + 1) % cities.size();
		auto less_city = uft.find(i);
		auto greater_city = uft.find(j);
		if (min_city_base[less_city] > min_city_base[greater_city]) {
			std::swap(less_city, greater_city);
		}
		const auto max = min_city_base[greater_city];
		const auto bullet_cost = cities[i].first;
		const auto merged = std::distance(merge.begin(), std::upper_bound(merge.begin(), merge.end(), bullet_cost - max));
		result += bullet_cost * (bullet.size() - merged) + merge_sum[merged] + merged * (long long int)max;
		uft.unite(i, j);
		min_city_base[uft.find(i)] = min_city_base[less_city];
	}
	const auto need = all_need(subway_size, subway_tree_edges, bullet);
	const auto min_base = std::distance(cities.begin(), std::min_element(cities.begin(), cities.end(), [](const auto a, const auto b) {return a.second < b.second; }));
	for (auto i = 0; i < cities.size(); ++i) {
		if (min_base == i) continue;
		result += (long long int)cities[i].second * (subway_size - bullet.size()) + need;
	}
	result += std::accumulate(subway_tree_edges.begin(), subway_tree_edges.end(), 0LL, [](const auto acc, const auto e) {return acc + std::get<2>(e); }) + (long long int)cities[min_base].second * (subway_size - 1LL);
	return result;
}
accuracy: 1
time_ms: 100
memory_kb: 7648
final_rank: 3