题目描述
在一场战争中,战场由n个岛屿和n-1个桥梁组成,保证每两个岛屿间有且仅有一条路径可达。现在,我军已经侦查到敌军的总部在编号为1的岛屿,而且他们已经没有足够多的能源维系战斗,我军胜利在望。已知在其他k个岛屿上有丰富能源,为了防止敌军获取能源,我军的任务是炸毁一些桥梁,使得敌军不能到达任何能源丰富的岛屿。由于不同桥梁的材质和结构不同,所以炸毁不同的桥梁有不同的代价,我军希望在满足目标的同时使得总代价最小。
侦查部门还发现,敌军有一台神秘机器。即使我军切断所有能源之后,他们也可以用那台机器。机器产生的效果不仅仅会修复所有我军炸毁的桥梁,而且会重新随机资源分布(但可以保证的是,资源不会分布到1号岛屿上)。不过侦查部门还发现了这台机器只能够使用m次,所以我们只需要把每次任务完成即可。
输入输出格式
输入格式:
第一行一个整数n,代表岛屿数量。
接下来n-1行,每行三个整数u,v,w,代表u号岛屿和v号岛屿由一条代价为c的桥梁直接相连,保证1<=u,v<=n且1<=c<=100000。
第n+1行,一个整数m,代表敌方机器能使用的次数。
接下来m行,每行一个整数ki,代表第i次后,有ki个岛屿资源丰富,接下来k个整数h1,h2,…hk,表示资源丰富岛屿的编号。
输出格式:
输出有m行,分别代表每次任务的最小代价。
输入输出样例
10 1 5 13 1 9 6 2 1 19 2 4 8 2 3 91 5 6 8 7 5 4 7 8 31 10 7 9 3 2 10 6 4 5 7 8 3 3 9 4 6
12 32 22
说明
【数据规模和约定】
对于10%的数据,2<=n<=10,1<=m<=5,1<=ki<=n-1
对于20%的数据,2<=n<=100,1<=m<=100,1<=ki<=min(10,n-1)
对于40%的数据,2<=n<=1000,m>=1,sigma(ki)<=500000,1<=ki<=min(15,n-1)
对于100%的数据,2<=n<=250000,m>=1,sigma(ki)<=500000,1<=ki<=n-1
这题没A,先放着,mlog^2n跑这个数据卡不过去
#include <iostream> #include <cstdlib> #include <cstdio> #include <algorithm> #include <string> #include <cstring> #include <cmath> #include <map> #include <stack> #include <set> #include <vector> #include <queue> #include <time.h> #define eps 1e-7 #define INF 0x3f3f3f3f #define MOD 1000000007 #define rep0(j,n) for(int j=0;j<n;++j) #define rep1(j,n) for(int j=1;j<=n;++j) #define pb push_back #define set0(n) memset(n,0,sizeof(n)) #define ll long long #define ull unsigned long long #define iter(i,v) for(edge *i=head[v];i;i=i->nxt) #define max(a,b) (a>b?a:b) #define min(a,b) (a<b?a:b) #define print_runtime printf("Running time:%.3lfs\n",double(clock())/1000.0) #define TO(j) printf(#j": %d\n",j); //#define OJ using namespace std; const int MAXINT = 250010; const int MAXNODE = 100010; const int MAXEDGE = 2 * MAXNODE; char BUF[30000000], *buf; int read() { int x = 0; while (!isdigit(*buf)) buf++; while (isdigit(*buf)) { x = x * 10 + *buf++ - '0';} return x; } //------------------- Head Files ----------------------// int toid[MAXINT]; struct res { int v, p; res(int _v, int _p) : v(_v), p(_p) {} res() {} }; res add(res a, res b) { return (a.v < b.v ? a : b); } struct node { int lb, rb; node *l, *r; res ans, org; int del, cv, rec; inline void recover() __attribute__((optimize("-O2"))){ del = 0; cv = INF; ans = org; rec = 1; } inline void cover(int c) __attribute__((optimize("-O2"))){ cv = ans.v = c; if (del) del = 0; } inline void dec(int c) __attribute__((optimize("-O2"))){ del += c; ans.v -= c; } inline void pushdown() __attribute__((optimize("-O2"))){ if (rec) { l->recover(); r->recover(); rec = 0; } if (cv != INF) { l->cover(cv); r->cover(cv); cv = INF; } if (del != 0) { l->dec(del); r->dec(del); del = 0; } } inline void pushup() __attribute__((optimize("-O2"))){ ans = add(l->ans, r->ans); } node() { ans.v = del = cv = INF; rec = 0; } }; int n, m, fa[MAXINT], sz[MAXINT], top[MAXINT], dfn[MAXINT], cnt_dfn = 1, dep[MAXINT], cnt, va[MAXINT], val[MAXINT], dfne[MAXINT]; struct SegTree { node mp[MAXINT * 4]; node *root; int _cnt; SegTree() { _cnt = 0; } inline node *newnode(int l, int r) __attribute__((optimize("-O2"))){ node *p = &mp[_cnt++]; p->lb = l; p->rb = r; return p; } inline void maketree(int lb, int rb, node *&p) __attribute__((optimize("-O2"))){ p = newnode(lb, rb); if (rb - lb > 1) { maketree(lb, (lb + rb) / 2, p->l); maketree((lb + rb) / 2, rb, p->r); p->pushup(); } else { p->ans.v = val[p->lb]; p->ans.p = lb; } p->org = p->ans; } inline void del(int lb, int rb, int c) __attribute__((optimize("-O2"))){ del(lb, rb, c, root); } inline void del(int lb, int rb, int c, node *p) __attribute__((optimize("-O2"))){ if (lb >= p->rb || rb <= p->lb) return; if (lb <= p->lb && rb >= p->rb) { p->dec(c); return; } p->pushdown(); del(lb, rb, c, p->l); del(lb, rb, c, p->r); p->pushup(); } inline void cover(int lb, int rb) __attribute__((optimize("-O2"))){ cover(lb, rb, root); } inline void cover(int lb, int rb, node *p) __attribute__((optimize("-O2"))){ if (lb >= p->rb || rb <= p->lb) return; if (lb <= p->lb && rb >= p->rb) { p->cover(0); return; } p->pushdown(); cover(lb, rb, p->l); cover(lb, rb, p->r); p->pushup(); } inline res query(int lb, int rb) __attribute__((optimize("-O2"))){ return query(lb, rb, root); } inline res query(int lb, int rb, node *p) __attribute__((optimize("-O2"))){ if (lb >= p->rb || rb <= p->lb) return res(INF, INF); if (lb <= p->lb && rb >= p->rb) return p->ans; p->pushdown(); return add(query(lb, rb, p->l), query(lb, rb, p->r)); } inline void recover() __attribute__((optimize("-O2"))){ root->recover(); } } st; struct edge { int u, v, l; edge *nxt; edge() {} edge(int _u, int _v, int _l, edge *_nxt) : u(_u), v(_v), l(_l), nxt(_nxt) {} } mp[MAXINT * 2], *head[MAXINT]; inline void addedge(int u, int v, int l) { mp[cnt] = edge(u, v, l, head[u]); head[u] = &mp[cnt++]; mp[cnt] = edge(v, u, l, head[v]); head[v] = &mp[cnt++]; } inline void dfs1(int p) { sz[p] = 1; iter(i, p) { if (i->v == fa[p])continue; fa[i->v] = p; dep[i->v] = dep[p] + 1; va[i->v] = i->l; dfs1(i->v); sz[p] += sz[i->v]; } } inline void dfs2(int p) { int mx = 0, gs = 0; dfn[p] = cnt_dfn++; iter(i, p) { if (i->v == fa[p]) continue; if (sz[i->v] > mx) { mx = sz[i->v]; gs = i->v; } } if (gs == 0) return; top[gs] = top[p]; dfs2(gs); iter(i, p) { if (i->v == fa[p] || i->v == gs) continue; top[i->v] = i->v; dfs2(i->v); } dfne[p] = cnt_dfn; } inline void modify(int l, int r, int c) { while (top[l] != top[r]) { if (dep[top[l]] > dep[top[r]]) { st.del(dfn[top[l]], dfn[l] + 1, c, st.root); l = fa[top[l]]; } else { st.del(dfn[top[r]], dfn[r] + 1, c, st.root); r = fa[top[r]]; } } st.del(min(dfn[r], dfn[l]), max(dfn[r], dfn[l]) + 1, c, st.root); } inline void cover(int p) { st.cover(dfn[p], dfne[p]); } inline res query(int l, int r) { res ans(INF, INF); while (top[l] != top[r]) { if (dep[top[l]] > dep[top[r]]) { ans = add(st.query(dfn[top[l]], dfn[l] + 1), ans); l = fa[top[l]]; } else { ans = add(st.query(dfn[top[r]], dfn[r] + 1), ans); r = fa[top[r]]; } } ans = add(st.query(min(dfn[r], dfn[l]), max(dfn[r], dfn[l]) + 1), ans); return ans; } inline void get_input() __attribute__((optimize("-O2"))); inline void work() __attribute__((optimize("-O2"))); int main() { get_input(); work(); return 0; } inline void work() { dfs1(1); dfs2(1); rep1(i, n) val[dfn[i]] = va[i]; rep1(i, n) toid[dfn[i]] = i; val[1] = INF; st.maketree(1, n + 1, st.root); while (m--) { st.recover(); int k = read(); ll ans = 0; while (k--) { int p = read(); res ret = query(1, p); ans += ret.v; cover(toid[ret.p]); modify(1, fa[toid[ret.p]], ret.v); } printf("%lld\n", ans); } } inline void get_input() { BUF[fread(BUF, 1, 30000000, stdin)] = '\0'; buf = BUF; n = read(); rep0(i, n - 1) { int u = read(), v = read(), l = read(); addedge(u, v, l); } m = read(); } /* 10 1 5 13 1 9 6 2 1 19 2 4 8 2 3 91 5 6 8 7 5 4 7 8 31 10 7 9 1 4 5 7 8 3 */