Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /// --- Shortest Path + Coin-Change(CC) --- ///
- #include <bits/stdc++.h>
- using namespace std;
- typedef pair<int , int> ii;
- typedef vector< int > vi;
- typedef vector< vi > vvi;
- #define PB push_back
- #define S second
- #define F first
- #define OO 1e9
- const int M = 1e5 + 5e1;
- const int N = 5e1 + 2e0;
- map<ii ,int> cost;
- map<ii , vi> path;
- vector< vi > tree;
- int memo[N][M];
- vi h ,p ,costs;
- int n ,m;
- /// --- Initialization before any test --- ///
- void init()
- {
- tree.clear();
- cost.clear();
- path.clear();
- costs.clear();
- h.assign(n + 1 ,0);
- p.assign(n + 1 ,1);
- tree.assign(n + 1 ,vi());
- }
- /// --- Return reversed vector --- ///
- inline vi reversed(vi a)
- {
- reverse(a.begin() ,a.end());
- return a;
- }
- /// --- Calculation height of node and get it's parent --- ///
- void DFS(int u ,int pa ,int H)
- {
- h[u] = H;
- p[u] = pa;
- for(int v : tree[u])
- if( v != pa )
- DFS(v ,u ,H + 1);
- }
- /// --- Get path between two nodes using their LCA --- ///
- vi getPath(int u ,int v)
- {
- vi p1;
- while( h[u] > h[v] )
- {
- p1.PB(u);
- u = p[u];
- }
- vi p2;
- while( h[u] < h[v] )
- {
- p2.PB(v);
- v = p[v];
- }
- while( u != v )
- {
- p1.PB(u);
- u = p[u];
- p2.PB(v);
- v = p[v];
- }
- p1.PB(u);
- vi p3;
- for(int i : p1) p3.PB(i);
- for(int i : reversed(p2)) p3.PB(i);
- return p3;
- }
- /// --- Pre-Processing all pathes to use them in DP --- ///
- void fillPath()
- {
- for(int u = 1 ; u < n ; u++)
- for(int v = u + 1 ; v <= n ; v++)
- path[ ii(u ,v) ] = getPath(u ,v),
- path[ ii(v ,u) ] = getPath(v ,u);
- }
- /// -- XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -- ///
- /// --- DP/Coin-Change --- ///
- int calc(int i ,int x)
- {
- if( i == (int)costs.size() || x <= 0 ) return !x ? 0 : OO;
- int &re = memo[i][x];
- if( re + 1 ) return re;
- re = OO;
- re = min(re ,calc(i ,x - 2 * costs[i]) + 2);
- re = min(re ,calc(i + 1 ,x));
- return re;
- }
- /// --- Get the costes on the path between two nodes (val of coins in CC)--- ///
- vi getCosts(int u ,int v)
- {
- vi res;
- vi Path = path[ ii(u ,v) ];
- for(int i = 0 ; i < (int)Path.size() - 1 ; i++)
- {
- int x = Path[ i ];
- int y = Path[i+1];
- res.PB( cost[ ii(x ,y) ] );
- }
- return res;
- }
- /// --- Solve the path like coin-change problem --- ///
- void CC(int u ,int v ,int c)
- {
- if( u != v )
- {
- int s = (int)(costs = getCosts(u ,v)).size();
- int sum = 0;
- for(int i : costs) sum += i;
- costs.pop_back();
- memset(memo ,-1 ,sizeof memo);
- int ans = calc(0 ,c - sum) + s;
- if( ans < (int)OO )
- {
- printf("Yes %d\n" ,ans);
- return;
- }
- puts("No");
- return;
- }
- if( c == 0 )
- {
- printf("Yes %d\n" ,c);
- return;
- }
- puts("No");
- }
- /// -- XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -- ///
- /// --- TestCase Solve --- ///
- void Solve()
- {
- scanf("%d%d" ,&n ,&m);
- init();
- for(int i = 0 ; i < m ; i++)
- {
- int u; scanf("%d" ,&u);
- int v; scanf("%d" ,&v);
- int c; scanf("%d" ,&c);
- cost[ ii(u ,v) ] = c;
- cost[ ii(v ,u) ] = c;
- tree[u].PB(v);
- tree[v].PB(u);
- }
- DFS(1 ,1 ,0);
- fillPath();
- int q;
- scanf("%d" ,&q);
- while( q-- )
- {
- int u; scanf("%d" ,&u);
- int v; scanf("%d" ,&v);
- int c; scanf("%d" ,&c);
- CC(u ,v ,c);
- }
- }
- /// --- Main --- ///
- int main()
- {
- int Tc;
- scanf("%d" ,&Tc);
- while( Tc-- )
- {
- Solve();
- if( Tc ) puts("");
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement