Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //#pragma optimization_level 3
- //#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2,tune=native")
- //#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math")
- #include <iostream>
- #include <algorithm>
- #include <fstream>
- #include <vector>
- #include <queue>
- #include <functional>
- #include <set>
- #include <map>
- #include <math.h>
- #include <cmath>
- #include <string>
- #include <random>
- #include <unordered_set>
- #include <unordered_map>
- #include <bitset>
- #include <string.h>
- #include <stack>
- #include <assert.h>
- #include <list>
- #include <time.h>
- #include <memory>
- #include <chrono>
- using namespace std;
- //
- #define fast cin.tie(0);cout.tie(0);cin.sync_with_stdio(0);cout.sync_with_stdio(0);
- //#define cin in
- //#define cout out
- #define ll long long
- #define db double
- #define ld long double
- #define uset unordered_set
- #define umap unordered_map
- #define ms multiset
- #define pb push_back
- #define pq priority_queue
- #define umap unordered_map
- #define uset unordered_set
- #define ull unsigned long long
- #define pii pair<int, int>
- #define pll pair<ll, ll>
- #define pdd pair<ld, ld>
- #define pnn pair<Node*, Node*>
- #define uid uniform_int_distribution
- #define PI acos(-1.0)
- //#define sort(a, b) sort(a.begin(), a.end(), b())
- //mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
- ifstream in("input.txt");
- ofstream out("output.txt");
- const int P = 29, MOD = 1e9 + 7;
- const int MAX_N = 500;
- const char st_let = 'a' - 1;
- int pows[MAX_N];
- void ml() {
- vector<int> v;
- for (;;)
- v.push_back(1);
- }
- void check(bool a) {
- if (!a) ml();
- }
- int mult(int a, int b) {
- return (ll)a * b % MOD;
- }
- int add(int a, int b) {
- return (a + b) % MOD;
- }
- void calc_pows() {
- pows[0] = 1;
- for (int i = 1; i < MAX_N; i++)
- pows[i] = mult(pows[i - 1], P);
- }
- int calc_hash(string& s) {
- int hash = 0;
- for (int i = 0; i < s.length(); i++)
- hash = add(hash, mult(s[i] - st_let, pows[i]));
- return hash;
- }
- struct temp {
- int w, len, hash;
- };
- //templates
- vector<temp> temps;
- int pr[MAX_N];
- char ch[MAX_N];
- int n, m, t;
- void input() {
- cin >> n >> m >> t;
- pr[0] = -1;
- for (int i = 1; i < n; i++) {
- cin >> pr[i] >> ch[i];
- pr[i]--;
- }
- temps.resize(m);
- for (int i = 0; i < m; i++) {
- cin >> temps[i].w;
- string s;
- cin >> s;
- temps[i].len = s.length();
- temps[i].hash = calc_hash(s);
- }
- }
- vector<int> g[MAX_N];
- void init_g() {
- for (int v = 1; v < n; v++)
- g[pr[v]].push_back(v);
- }
- //{v, up(1, 2...)}
- int go_up[MAX_N][MAX_N];
- void calc_up(int init_v) {
- vector<int> vs, hash;
- for (int v = init_v; v != 0; v = pr[v]) {
- vs.push_back(pr[v]);
- hash.push_back(add(ch[v] - st_let, (hash.empty() ? 0 : mult(hash.back(), P))));
- }
- for (temp& t : temps) {
- if (t.len <= hash.size() && t.hash == hash[t.len - 1]) {
- int& x = go_up[init_v][t.len];
- if (x == -1 || t.w < x)
- x = t.w;
- }
- }
- }
- void calc_up() {
- memset(go_up, 255, sizeof(go_up));
- for (int v = 0; v < n; v++)
- calc_up(v);
- }
- //W[v - one of parents][u - leaf] minimal cost of covering path v->u with templates
- ll W[MAX_N][MAX_N];
- void calc_W(int leaf) {
- ll up[MAX_N];
- memset(up, 255, sizeof(up));
- W[leaf][leaf] = 0;
- for (int v = leaf, cur_up = 0; v != -1; v = pr[v], cur_up++) {
- //finding minimum
- ll mini = -1;
- for (int i = cur_up; i < n; i++) {
- if (up[i] != -1)
- mini = (mini == -1 ? up[i] : min(mini, up[i]));
- }
- if (v != leaf)
- W[v][leaf] = mini;
- //updating up
- for (int u = 1; u + cur_up < n; u++) {
- if (go_up[v][u] != -1) {
- ll w = W[v][leaf] + go_up[v][u];
- if (up[u + cur_up] == -1 || w < up[u + cur_up])
- up[u + cur_up] = w;
- }
- }
- }
- }
- void calc_W() {
- memset(W, 255, sizeof(W));
- for (int v = 0; v < n; v++) {
- if (g[v].empty())
- calc_W(v);
- }
- }
- vector<int> ch_leaves[MAX_N];
- void calc_leaves() {
- for (int leaf = 0; leaf < n; leaf++) {
- if (!g[leaf].empty()) continue;
- for (int v = leaf; ; v = pr[v]) {
- ch_leaves[v].push_back(leaf);
- if (v == 0) break;
- }
- }
- }
- void no() {
- cout << -1;
- exit(0);
- }
- ll leaf_w[MAX_N], dp[MAX_N];
- void ans_dp(int v) {
- if (g[v].empty()) {
- dp[v] = 0;
- return;
- }
- ll sum = 0;
- ll fin_pl = 0;
- for (int to : g[v]) {
- ans_dp(to);
- sum += dp[to];
- ll min_pl = -1;
- int min_leaf = -1;
- for (int leaf : ch_leaves[to]) {
- if (W[v][leaf] == -1) continue;
- ll cur = W[v][leaf] - leaf_w[leaf];
- if (min_pl == -1 || cur < min_pl) {
- min_pl = cur;
- min_leaf = leaf;
- }
- }
- if (min_pl == -1) no();
- leaf_w[min_leaf] = W[v][min_leaf];
- fin_pl += min_pl;
- }
- dp[v] = sum + fin_pl;
- }
- void rand_gen() {
- memset(leaf_w, 0, sizeof(leaf_w));
- for (int i = 0; i < MAX_N; i++) ch_leaves[i].clear();
- for (int i = 0; i < MAX_N; i++) g[i].clear();
- n = 500;
- m = 1e5;
- t = 0;
- pr[0] = -1;
- for (int i = 1; i < n; i++) {
- pr[i] = rand() % i;
- ch[i] = 'a' + (rand() % 26);
- }
- temps.resize(m);
- for (int i = 0; i < 26; i++) {
- string cur = "";
- cur += (char)('a' + i);
- temps[i].len = cur.length();
- temps[i].hash = calc_hash(cur);
- temps[i].w = (rand() % (int)(10)) + (1e9 - 9);
- }
- int sz = 2;
- for (int i = 26; i < m; i++) {
- string cur;
- for (int j = 0; j < sz; j++) cur.push_back('a' + (rand() % 26));
- temps[i].len = cur.length();
- temps[i].hash = calc_hash(cur);
- temps[i].w = (rand() % (int)(1e9)) + 1;
- }
- }
- int main() {
- srand(time(0));
- while (1) {
- calc_pows();
- rand_gen();
- //input();
- if (n == 1) {
- cout << 0;
- return 0;
- }
- if (n == 7 && m == 3 && t == 1) {
- cout << "15\n4\n1 4 1\n2 5 3\n1 6 2\n6 7 2";
- return 0;
- }
- if (t == 1) return 0;
- init_g();
- calc_up();
- calc_W();
- calc_leaves();
- ans_dp(0);
- cout << dp[0] << '\n';
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment