Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Knapsack DP is harder than FFT.
- #include<bits/stdc++.h>
- using namespace std;
- typedef int64_t ll; typedef pair<int,int> pii; typedef pair<ll,ll> pll;
- #define ff first
- #define ss second
- #define pb emplace_back
- #define FOR(i,n) for(int i=0;i<(n);++i)
- #define FOO(i,a,b) for(int i=(a);i<=int(b);++i)
- #define OOF(i,a,b) for(int i=(a);i>=int(b);--i)
- #define AI(x) begin(x),end(x)
- template<class I>bool chmax(I&a,I b){return a<b?(a=b,true):false;}
- template<class I>bool chmin(I&a,I b){return b<a?(a=b,true):false;}
- inline ll cdiv(ll x,ll m){return x/m+(x%m?(x<0)^(m>0):0);}
- #ifdef OWO
- #define safe cerr<<"\033[1;32m"<<__PRETTY_FUNCTION__<<" - "<<__LINE__<<" JIZZ\033[0m\n"
- #define debug(args...) SDF(#args, args)
- #define OIU(args...) ostream& operator<<(ostream&O,args)
- #define LKJ(S,B,E,F) template<class...T>OIU(S<T...>s){O<<B;int c=0;for(auto i:s)O<<(c++?", ":"")<<F;return O<<E;}
- LKJ(vector,'[',']',i)LKJ(deque,'[',']',i)LKJ(set,'{','}',i)LKJ(multiset,'{','}',i)LKJ(unordered_set,'{','}',i)LKJ(map,'{','}',i.ff<<':'<<i.ss)LKJ(unordered_map,'{','}',i.ff<<':'<<i.ss)
- template<class T,size_t N>OIU(array<T,N>a){return O<<vector<T>(AI(a));}template<class...T>OIU(pair<T...>p){return O<<'('<<p.ff<<','<<p.ss<<')';}template<class...T>OIU(tuple<T...>t){return O<<'(',apply([&O](T...s){int c=0;(...,(O<<(c++?", ":"")<<s));},t),O<<')';}
- template<class...T>void SDF(const char* s,T...a){int c=sizeof...(T);if(!c){cerr<<"\033[1;32mvoid\033[0m\n";return;}(cerr<<"\033[1;32m("<<s<<") = (",...,(cerr<<a<<(--c?", ":")\033[0m\n")));}
- #else
- #pragma GCC optimize("Ofast")
- #define safe ((void)0)
- #define debug(...) ((void)0)
- #endif
- const ll inf = 1e9, INF = 4e18;
- struct Solver{
- static const int inf = 1e9;
- struct route{
- int dis, head, tail;
- route(int d = inf, int h = -1, int t = -1):
- dis(d), head(h), tail(t){}
- bool operator<(const route &rhs){
- if(dis != rhs.dis) return dis < rhs.dis;
- return tail < rhs.tail;
- }
- };
- struct eek{
- // store best two ans
- // with different color
- route one, two;
- eek(): one(), two(){}
- eek(route a, route b): one(a), two(b){}
- void upd(route cur){
- if(cur < one) swap(cur, one);
- // if best and cur are in
- // same color, then discard
- // the worse one
- if(cur.tail == one.tail) return;
- if(cur < two) swap(cur, two);
- }
- };
- eek merge(eek a, eek b){
- eek anss;
- for(route x: {a.one, a.two}) for(route y: {b.one, b.two})
- if(x.tail != y.head)
- anss.upd(route(x.dis + y.dis, x.head, y.tail));
- return anss;
- }
- int n;
- vector<vector<eek>> dp;
- map<string, int> mp;
- Solver(){}
- void init(int _n){
- n = _n;
- dp.assign(n, vector<eek>(n));
- mp.clear();
- }
- void addEdge(int u, int v, int c){
- route e(1, c, c);
- dp[u][v].upd(e);
- dp[v][u].upd(e);
- }
- void fw(){
- for(int k = 0; k < n; ++k)
- for(int i = 0; i < n; ++i)
- for(int j = 0; j < n; ++j){
- eek tmp = merge(dp[i][k], dp[k][j]);
- dp[i][j].upd(tmp.one);
- dp[i][j].upd(tmp.two);
- }
- }
- void solve(){
- int n, m, q;
- cin >> n >> m;
- init(n);
- for(int i = 0; i < n; ++i){
- string s; cin >> s;
- mp[s] = i;
- }
- for(; m; --m){
- int u, v, c;
- cin >> u >> v >> c;
- addEdge(u, v, c);
- }
- fw();
- fw();
- fw();
- for(cin >> q; q; --q){
- string a, b; int u, v;
- cin >> a >> b;
- bool no = false;
- if(mp.count(a)) u = mp[a]; else no = true;
- if(mp.count(b)) v = mp[b]; else no = true;
- if(dp[u][v].one.dis == inf) no = true;
- if(no) cout << "HweiBuHweiChiShiTaShi...\n";
- else cout << dp[u][v].one.dis << '\n';
- if(!no) assert(dp[u][v].one.dis == dp[v][u].one.dis);
- }
- }
- } solver;
- int32_t main(){
- ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
- solver.solve();
- return 0;
- }
Add Comment
Please, Sign In to add comment