# | Time | Username | Problem | Language | Result | Execution time | Memory |
---|---|---|---|---|---|---|---|
876093 | danikoynov | Reconstruction Project (JOI22_reconstruction) | C++14 | 0 ms | 0 KiB |
This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
typedef long long ll;
const int maxn = 510, maxm = 1e5 + 10, maxq = 1e6 + 10;
const ll inf = 1e18;
struct edge
{
int v, u;
ll w;
edge(int _v = 0, int _u = 0, ll _w = 0)
{
v = _v;
u = _u;
w = _w;
}
bool operator < (const edge &e) const
{
return w < e.w;
}
}edges[maxm];
int n, m, q;
ll ans[maxq];
struct query
{
int idx;
ll x;
bool operator < (const query &q1) const
{
return x < q1.x;
}
}task[maxq];
void input()
{
cin >> n >> m;
for (int i = 1; i <= m; i ++)
{
cin >> edges[i].v >> edges[i].u >> edges[i].w;
}
cin >> q;
for (int i = 1; i <= q; i ++)
{
cin >> task[i].x;
task[i].idx = i;
}
sort(edges + 1, edges + m + 1);
sort(task + 1, task + q + 1);
}
int par[maxn];
int find_leader(int v)
{
return (par[v] == v) ? v : (par[v] = find_leader(par[v]));
}
bool unite(int v, int u)
{
v = find_leader(v);
u = find_leader(u);
if (v == u)
return false;
if (rand % 2 == 0)
par[v] = u;
else
par[u] = v;
return true;
}
vector < int > down_list[maxm], up_list[maxm];
void offline_mst()
{
vector < int > new_list;
for (int i = 1; i <= m; i ++)
{
for (int j = 1; j <= n; j ++)
par[j] = j;
new_list.clear();
new_list.push_back(i);
unite(edges[i].v, edges[i].u);
for (int j = 0; j < down_list[i - 1].size(); j ++)
{
if (unite(edges[down_list[i - 1][j]].v, edges[down_list[i - 1][j]].u))
new_list.push_back(down_list[i - 1][j]);
}
///reverse(new_list.begin(), new_list.end());
down_list[i] = new_list;
///assert(new_list.size() < n);
}
for (int i = m; i > 0; i --)
{
for (int j = 1; j <= n; j ++)
par[j] = j;
new_list.clear();
new_list.push_back(i);
unite(edges[i].v, edges[i].u);
for (int j = 0; j < up_list[i + 1].size(); j ++)
{
if (unite(edges[up_list[i + 1][j]].v, edges[up_list[i + 1][j]].u))
new_list.push_back(up_list[i + 1][j]);
}
up_list[i] = new_list;
/**cout << "-----------" << endl;
for (int cur : up_list[i])
cout << cur << " ";
cout << endl;*/
///assert(new_list.size() < n);
}
}
void answer()
{
int pt = 1;
for (int i = 1; i <= q; i ++)
{
while(pt <= m && edges[pt].w < task[i].x)
pt ++;
pt --;
int lf = 0, rf = 0;
for (int j = 1; j <= n; j ++)
par[j] = j;
int cnt = 0;
ll sum = 0;
while(cnt < n - 1)
{
ll w_lf = inf, w_rf = inf;
if (lf < down_list[pt].size()) w_lf = task[i].x - edges[down_list[pt][lf]].w;
if (rf < up_list[pt + 1].size()) w_rf = edges[up_list[pt + 1][rf]].w - task[i].x;
if (w_lf < w_rf)
{
bool tie = unite(edges[down_list[pt][lf]].v, edges[down_list[pt][lf]].u);
if (tie)
{
sum = sum + task[i].x - edges[down_list[pt][lf]].w;
cnt ++;
}
lf ++;
}
else
{
bool tie = unite(edges[up_list[pt + 1][rf]].v, edges[up_list[pt + 1][rf]].u);
if (tie)
{
///cout << task[i].x << " :: " << edges[up_list[pt + 1][lf]].w << endl;
sum = sum + edges[up_list[pt + 1][rf]].w - task[i].x;
cnt ++;
}
rf ++;
}
}
ans[task[i].idx] = sum;
}
for (int i = 1; i <= q; i ++)
cout << ans[i] << endl;
}
void solve()
{
input();
offline_mst();
answer();
}
void speed()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
}
int main()
{
speed();
solve();
return 0;
}