Submission #39207

# Submission time Handle Problem Language Result Execution time Memory
39207 2018-01-10T07:04:04 Z qoo2p5 Toll (APIO13_toll) C++14
16 / 100
6 ms 2896 KB
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;

const int INF = (int) 1e9 + 1e6 + 123;
const ll LINF = (ll) 1e18 + 1e9 + 123;
const ld EPS = (ld) 1e-7;
const ll MOD = (ll) 1e9 + 7;

#define sz(x) (int) (x).size()
#define mp(x, y) make_pair(x, y)
#define pb push_back
#define all(x) (x).begin(), (x).end()
#define lb(s, t, x) (int) (lower_bound(s, t, x) - s)
#define ub(s, t, x) (int) (upper_bound(s, t, x) - s)
#define rep(i, f, t) for (int i = f; i < t; i++)
#define per(i, f, t) for (int i = f; i >= t; i--)

ll power(ll x, ll y, ll mod = MOD) {
    if (y == 0) {
        return 1;
    }
    if (y & 1) {
        return power(x, y - 1, mod) * x % mod;
    } else {
        ll tmp = power(x, y / 2, mod);
        return tmp * tmp % mod;
    }
}

template<typename A, typename B> bool mini(A &x, const B &y) {
    if (y < x) {
        x = y;
        return true;
    }
    return false;
}

template<typename A, typename B> bool maxi(A &x, const B &y) {
    if (y > x) {
        x = y;
        return true;
    }
    return false;
}

void add(ll &x, ll y) {
	x += y;
	if (x >= MOD) x -= MOD;
	if (x < 0) x += MOD;
}

ll mult(ll x, ll y) {
	return x * y % MOD;
}

void run();

#define TASK ""

int main() {
#ifdef LOCAL
    if (strlen(TASK) > 0) {
        cerr << "Reminder: you are using file i/o, filename: " TASK "!" << endl << endl;
    }
#endif
#ifndef LOCAL
    if (strlen(TASK)) {
        freopen(TASK ".in", "r", stdin);
        freopen(TASK ".out", "w", stdout);
    }
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
#endif
    cout << fixed << setprecision(12);
    run();
    return 0;
}

// == SOLUTION == //

const int N = 5005;
const int L = 13;

struct Edge {
	int u, v, c;
	
	bool operator<(const Edge &e) const {
		return c < e.c;
	}
};

int n, m, k;
ll amount[N], n_amount[N];
Edge e[N], my[N];
int id[N];
int p[N];
vector<pair<int, int>> g[N];

int get(int v) {
	return (p[v] == v ? v : (p[v] = get(p[v])));
}

bool unite(int u, int v) {
	u = get(u);
	v = get(v);
	if (u == v) {
		return 0;
	}
	p[u] = v;
	return 1;
}

void clr() {
	rep(i, 0, n + 1) {
		p[i] = i;
		g[i].clear();
	}
}

int depth[N];
int up[N][L];
int tin[N], tout[N];
int tmr;

void calc_up(int v, int f = -1) {
	if (f == -1) {
		tmr = 0;
		fill(up[v], up[v] + L, v);
		depth[v] = 0;
	} else {
		up[v][0] = f;
		rep(i, 1, L) {
			up[v][i] = up[up[v][i - 1]][i - 1];
		}
	}
	tin[v] = tmr++;
	for (auto &e : g[v]) {
		int u = e.first;
		if (u == f) {
			continue;
		}
		depth[u] = depth[v] + 1;
		calc_up(u, v);
	}
	tout[v] = tmr - 1;
}

int go(int v, int h) {
	rep(i, 0, L) {
		if (h & (1 << i)) {
			v = up[v][i];
		}
	}
	return v;
}

int lca(int u, int v) {
	if (depth[u] < depth[v]) {
		swap(u, v);
	}
	u = go(u, depth[u] - depth[v]);
	if (u == v) return u;
	per(i, L - 1, 0) {
		int uu = up[u][i];
		int vv = up[v][i];
		if (uu != vv) {
			u = uu;
			v = vv;
		}
	}
	return up[u][0];
}

bool check_st(int st, int v) {
	return tin[st] <= tin[v] && tout[v] <= tout[st];
}

bool check_path(int u, int v, int w, int a, int b) {
	if (depth[a] < depth[b]) {
		swap(a, b);
	}
	return !check_st(a, w) && (check_st(a, u) || check_st(a, v));
}

bool taken[N];
ll mi[N];
vector<pair<ll, ll>> opt;

ll dfs(int v, int f = -1) {
	ll res = amount[v];
	for (auto &e : g[v]) {
		int u = e.first;
		if (u == f) {
			continue;
		}
		int id = e.second;
		ll t = dfs(u, v);
		if (id >= 0) {
			opt.pb({t, mi[id]});
		}
		res += t;
	}
	return res;
}

void run() {
	cin >> n >> m >> k;
	rep(i, 0, m) {
		cin >> e[i].u >> e[i].v >> e[i].c;
	}
	sort(e, e + m);
	rep(i, 0, k) {
		cin >> my[i].u >> my[i].v;
	}
	rep(i, 1, n + 1) {
		cin >> amount[i];
	}
	
	{
		clr();
		rep(i, 0, k) {
			unite(my[i].u, my[i].v);
		}
		vector<int> used;
		rep(i, 0, m) {
			if (unite(e[i].u, e[i].v)) {
				used.pb(i);
			}
		}
		
		clr();
		for (int i : used) {
			unite(e[i].u, e[i].v);
		}
		
		int ptr = 1;
		
		rep(i, 1, n + 1) {
			int v = get(i);
			if (!id[v]) {
				id[v] = ptr++;
			}
			id[i] = id[v];
			n_amount[id[v]] += amount[i];
		}
		
		copy(n_amount, n_amount + ptr, amount);
		rep(i, 0, k) {
			my[i].u = id[my[i].u];
			my[i].v = id[my[i].v];
		}
		
		map<pair<int, int>, int> edges;
		rep(i, 0, m) {
			int u = id[e[i].u];
			int v = id[e[i].v];
			if (u > v) swap(u, v);
			if (edges.count({u, v})) mini(edges[{u, v}], e[i].c);
			else edges[{u, v}] = e[i].c;
		}
		ptr = 0;
		for (auto &it : edges) {
			e[ptr++] = {it.first.first, it.first.second, it.second};
		}
		m = ptr;
	}
	
	ll ans = 0;
	
	rep(mask, 1, 1 << k) {
		clr();
		bool ok = 1;
		int cnt = 0;
		rep(i, 0, k) {
			if (mask & (1 << i)) {
				ok &= unite(my[i].u, my[i].v);
				g[my[i].u].pb({my[i].v, i});
				g[my[i].v].pb({my[i].u, i});
				cnt++;
			}
		}
		if (!ok) {
			continue;
		}
		
		memset(taken, 0, sizeof taken);
		rep(i, 0, m) {
			if (unite(e[i].u, e[i].v)) {
				g[e[i].u].pb({e[i].v, -1});
				g[e[i].v].pb({e[i].u, -1});
				taken[i] = 1;
			}
		}
		
		fill(mi, mi + k, LINF);
		calc_up(1);
		
		rep(i, 0, m) {
			if (!taken[i]) {
				int u = e[i].u;
				int v = e[i].v;
				int w = lca(u, v);

				rep(j, 0, k) {
					if (!(mask & (1 << j))) {
						continue;
					}
					
					int a = my[j].u;
					int b = my[j].v;
					assert(abs(depth[a] - depth[b]) == 1);
					if (check_path(u, v, w, a, b)) {
						mini(mi[j], e[i].c);
					}
				}
			}
		}
		
		opt.clear();
		dfs(1);
		assert(sz(opt) == cnt);
		ll cur = 0;
		for (auto &it : opt) {
			cur += it.first * it.second;
		}
		maxi(ans, cur);
	}
	
	cout << ans << "\n";
}

Compilation message

toll.cpp: In function 'int main()':
toll.cpp:72:40: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)', declared with attribute warn_unused_result [-Wunused-result]
         freopen(TASK ".in", "r", stdin);
                                        ^
toll.cpp:73:42: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)', declared with attribute warn_unused_result [-Wunused-result]
         freopen(TASK ".out", "w", stdout);
                                          ^
# Verdict Execution time Memory Grader output
1 Correct 0 ms 2896 KB Output is correct
2 Correct 0 ms 2896 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 0 ms 2896 KB Output is correct
2 Correct 0 ms 2896 KB Output is correct
3 Incorrect 6 ms 2896 KB Output isn't correct
4 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Correct 0 ms 2896 KB Output is correct
2 Correct 0 ms 2896 KB Output is correct
3 Incorrect 6 ms 2896 KB Output isn't correct
4 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Correct 0 ms 2896 KB Output is correct
2 Correct 0 ms 2896 KB Output is correct
3 Incorrect 6 ms 2896 KB Output isn't correct
4 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Correct 0 ms 2896 KB Output is correct
2 Correct 0 ms 2896 KB Output is correct
3 Incorrect 6 ms 2896 KB Output isn't correct
4 Halted 0 ms 0 KB -