제목 설명
전쟁에서 N-1로 구성된 n 개의 섬과 다리에 의해 전장마다 두 섬 사이에 하나 개의 경로 만 거기 있는지 확인합니다. 이제 우리 군은 섬에 대한 제 1의 적의 본부를 감지 할 수있다, 그들은 전투, 눈에 군사적 승리를 유지하기 위해 충분한 에너지를 가지고 있지 않습니다. 에너지 적 접근을 방지하기 위해, 다른 섬의 K에 풍부한 에너지를 가지고 알려진 우리의 군사 임무의 일부는 적의 어떤 에너지가 풍부한 섬에 도달 할 수 있도록 다리를 폭파하는 것입니다. 때문에 다른 재료와 다리의 다른 구조로, 다리는, 다른 서로 다른 가격이 날려 총 비용을 최소화하기 위해 목표를 충족시키면서 우리의 군사를 희망합니다.
조사 부서는 신비한 적 기계가 있음을 발견했다. 군대는 모든 에너지를 차단 후에도, 그들은 또한 그 기계를 사용할 수 있습니다. 기계 생성 효과는 다리를 폭파하기 위해 군사를 모두 해결되지 않습니다 및 자원의 분포 난수를 다시 것입니다 (하지만 당신은 자원이 섬에 제 1 호에 배포되지 않도록 보장 할 수 있습니다). 그러나 조사는 또한 부서는이 기계 m 시간을 사용할 수 있다는 것을 발견, 그래서 우리는 단지 각 작업을 완료해야합니다.
입력 형식
제 라인 정수 n은, 섬의 수를 나타낸다.
다음에, N-1 세 정수 선 U, V는 W는 U가되도록 직접 고려하여 연결된 섬의 수 및 섬 다리 번호 v에 C를 나타내는 <= U, V <= N-1 <= 그 C <= 100,000.
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 4 5
7 8 31
10 9 7
3
2 6 10
4 5 7 8 3
3 6 9 4
12
32
22
설명 / 팁
[데이터] 규모 규칙
10 %, 2 <=는 N <= 10,1 <= m <= 5,1 <= KI <= N-1이 데이터
20 %의 데이터 (2) <= N <= 100,1 <= m <= 100,1 <= KI <= 분 (10, N-1)
40 %의 데이터 (2) <= N <= 1000, m> = 1, 시그마 (KI) <= 500000,1 <= KI <= 분 (15, N-1)
데이터의 100 %, 2 <= N <= 250,000, m> = 1, 시그마 (KI) <= 500000,1 <= KI <= N-1이
해결책:
각 쿼리 키포인트 들어, 두 지점 사이의 가상 에지 가중치의 설정은, 두 지점 사이의 원래 트리 경로에 낮은 값이고
DP 시간이 포인트가 핵심이다, 플러스 측의 권리
그렇지 않은 경우, 최소 추가 (오른쪽, 그것은 오프이 하위 트리 아들의 모든 주요 지점 소요)
암호:
#include"iostream" #include"algorithm" #include"vector" #include"stdio.h" using namespace std; #define ll long long #define rep(i,a,b) for(int i=a;i<=b;i++) const int N = 250007; vector<int> RG[N],VG[N]; int U[N],V[N],C[N]; int dfn[N],deep[N]; ll me[N]; int fa[N][20]; int stk[N],top; int idq[N],mark[N]; int n,m,idx; int f[N][20]; int dp[N]; struct aa { int so; int w; }; vector<aa> G[N]; int LCA(int u,int v) { if(deep[u] < deep[v]) swap(u,v); int delta = deep[u] - deep[v]; for(int i = 19; i >= 0; --i) { if((delta >> i) & 1) u = fa[u][i]; } for(int i = 19; i >= 0; --i) { if(fa[u][i] != fa[v][i]) u = fa[u][i],v = fa[v][i]; } if(u == v) return u; return fa[u][0]; } int DIS(int u,int v) { if(deep[u] < deep[v]) swap(u,v); int delta = deep[u] - deep[v]; int ans=1e16; for(int i = 19; i >= 0; --i) { if((delta >> i) & 1) ans=min(ans,f[u][i]),u = fa[u][i]; } if(u == v) return ans; for(int i = 19; i >= 0; --i) { if(fa[u][i] != fa[v][i]) u = fa[u][i],v = fa[v][i]; } return fa[u][0]; } void insert2(int u) { if(top == 1) { stk[++top] = u; return; } int lca = LCA(u,stk[top]); if(lca == stk[top]) { stk[++top] = u; return ; } while(top > 1 && dfn[lca] <= dfn[stk[top-1]]) { G[stk[top-1]].push_back({stk[top],DIS(stk[top],stk[top-1])}); --top; } if(lca != stk[top]) { G[lca].push_back({stk[top],DIS(stk[top],lca)}); stk[top] = lca; } stk[++top] = u; } ll dp2(int x) { ll cost=0; int len=G[x].size(); for(int j=0;j<len;j++) { aa i=G[x][j]; if(mark[i.so])cost+=i.w; else cost+=min(1ll*i.w,dp2(i.so)); } return cost; } void Clear(int x) { int len=G[x].size(); for(int j=0;j<len;j++) { aa i=G[x][j]; Clear(i.so); } G[x].clear(); } /***********************************/ void dfs(int u) { dfn[u] = ++idx; deep[u] = deep[fa[u][0]] + 1; int len=RG[u].size(); for(int j=0;j<len;j++) { int e=RG[u][j]; int v = U[e] ^ V[e] ^ u; if(v == fa[u][0]) continue; me[v] = C[e]; f[v][0]=C[e]; if(u != 1 && me[u] < me[v]) me[v] = me[u]; fa[v][0] = u; dfs(v); } } bool comp(int a,int b) { return dfn[a] < dfn[b]; } /***********************************/ #define sc(x) scanf("%d",&(x)) signed main() { cin >> n; for(int i = 1; i < n; ++i) { sc(U[i]); sc(V[i]); sc(C[i]); RG[U[i]].push_back(i); RG[V[i]].push_back(i); } dfs(1); for(int t = 1; t <= 19; ++t) for(int i = 1; i <= n; ++i) { fa[i][t] = fa[fa[i][t-1]][t-1]; if(fa[i][t]) f[i][t] = min(f[i][t-1] , f[fa[i][t-1]][t-1]); } cin >> m; for(int i = 0; i < m; ++i) { int sz; sc(sz); for(int j = 0; j < sz; ++j) { sc(idq[j]); mark[idq[j]] = 1; } sort(idq,idq+sz,comp); top = 0; stk[++top] = 1; for(int j = 0; j < sz; ++j) insert2(idq[j]); while(top > 0) { G[stk[top-1] ].push_back({stk[top],DIS(stk[top-1],stk[top])}); top--; } printf("%lld\n",dp2(1)); Clear(1); for(int j = 0; j < sz; ++j) mark[idq[j]] = 0; } return 0; }