[bzoj3611] [HEOI2014]大工程
阿新 • • 發佈:2019-01-04
國家 () 表示 head ... 都是 現在 put --
Description
國家有一個大工程,要給一個非常大的交通網絡裏建一些新的通道。
我們這個國家位置非常特殊,可以看成是一個單位邊權的樹,城市位於頂點上。
在 2 個國家 a,b 之間建一條新通道需要的代價為樹上 a,b 的最短路徑。
現在國家有很多個計劃,每個計劃都是這樣,我們選中了 k 個點,然後在它們兩兩之間 新建 C(k,2)條 新通道。
現在對於每個計劃,我們想知道:
1.這些新通道的代價和
2.這些新通道中代價最小的是多少
3.這些新通道中代價最大的是多少
Input
第一行 n 表示點數。
接下來 n-1 行,每行兩個數 a,b 表示 a 和 b 之間有一條邊。
點從 1 開始標號。 接下來一行 q 表示計劃數。
對每個計劃有 2 行,第一行 k 表示這個計劃選中了幾個點。
第二行用空格隔開的 k 個互不相同的數表示選了哪 k 個點。
Output
輸出 q 行,每行三個數分別表示代價和,最小代價,最大代價。
Sample Input
10
2 1
3 2
4 1
5 2
6 4
7 5
8 6
9 7
10 9
5
2
5 4
2
10 4
2
5 2
2
6 1
2
6 1
Sample Output
3 3 3
6 6 6
1 1 1
2 2 2
2 2 2
Solution
入門級的\(dp\)放虛樹上變省選難度。。
建虛樹然後無腦\(dp\)就行。
註意註釋的地方,小細節要註意。
#include<bits/stdc++.h> using namespace std; #ifdef ONLINE_JUDGE #define getchar() ((p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin)),p1==p2)?EOF:*p1++) #endif namespace fast_IO { char buf[1<<21],*p1=buf,*p2=buf; template <typename T> inline void read(T &x) { x=0;T f=1;char ch=getchar(); for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f; for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f; } template <typename T,typename... Args> inline void read(T& x,Args& ...args) { read(x),read(args...); } char buf2[1<<21],a[80];int p,p3=-1; inline void flush() {fwrite(buf2,1,p3+1,stdout),p3=-1;} template <typename T> inline void write(T x,char ch) { if(p3>(1<<20)) flush(); if(x<0) buf2[++p3]='-',x=-x; do {a[++p]=x%10+48;} while(x/=10); do {buf2[++p3]=a[p];} while(--p); buf2[++p3]=ch; } } using fast_IO :: read; using fast_IO :: write; using fast_IO :: flush; const int maxn = 1e6+10; const int N = 2e6+10; #define ll long long int dep[maxn],sz[maxn],dfn[maxn],n; struct Normal_Tree { int head[maxn],tot,f[maxn][21],dfn_cnt; struct edge{int to,nxt;}e[maxn<<1]; void add(int u,int v) {e[++tot]=(edge){v,head[u]},head[u]=tot;} void ins(int u,int v) {add(u,v),add(v,u);} void dfs(int x,int fa) { f[x][0]=fa,dep[x]=dep[fa]+1,dfn[x]=++dfn_cnt,sz[x]=1; for(int i=1;i<=20;i++) f[x][i]=f[f[x][i-1]][i-1]; for(int i=head[x];i;i=e[i].nxt) if(e[i].to!=fa) dfs(e[i].to,x),sz[x]+=sz[e[i].to]; } int lca(int x,int y) { if(dep[x]<dep[y]) swap(x,y); for(int i=20;~i;i--) if(dep[f[x][i]]>=dep[y]) x=f[x][i]; if(x==y) return x; for(int i=20;~i;i--) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i]; return f[x][0]; } }T; int cmp(int x,int y) {return dfn[x]<dfn[y];} struct Virtual_Tree { int head[N],tot,cnt,in[N],tag[N],sta[N],use[N],k,mn[N],mn2[N],mx[N],mx2[N],Min,Max,vis[N]; ll ans; struct edge{int to,nxt,w;}e[N<<1]; void add(int u,int v,int w) {e[++tot]=(edge){v,head[u],w},head[u]=tot;} void ins(int u,int v,int w) {add(u,v,w),add(v,u,w);} void dfs(int x,int fa) { mn[x]=mn2[x]=1e9,mx[x]=mx2[x]=0; int bo=0; for(int i=head[x];i;i=e[i].nxt) if(e[i].to!=fa) { dfs(e[i].to,x);bo=1; ans+=1ll*e[i].w*(k-tag[e[i].to])*tag[e[i].to]; tag[x]+=tag[e[i].to]; mx[e[i].to]+=e[i].w; mx2[e[i].to]+=e[i].w; mn[e[i].to]+=e[i].w; mn2[e[i].to]+=e[i].w; //printf("edge :: %d %d %d\n",x,e[i].to,mn[e[i].to]); if(mx[e[i].to]>mx[x]) mx2[x]=mx[x],mx[x]=mx[e[i].to]; else if(mx[e[i].to]>mx2[x]) mx2[x]=mx[e[i].to]; if(mn[e[i].to]<mn[x]) mn2[x]=mn[x],mn[x]=mn[e[i].to]; else if(mn[e[i].to]<mn2[x]) mn2[x]=mn[e[i].to]; } if(mx2[x]) Min=min(Min,mn[x]+mn2[x]),Max=max(Max,mx[x]+mx2[x]); //printf("Dfs :: %d %d %d\n",x,mn[x],mn2[x]); if(vis[x]) { Min=min(Min,mn[x]); Max=max(Max,mx[x]); mn2[x]=mn[x],mn[x]=0; // important !!! } if(!bo) mn2[x]=mn[x]=mx[x]=mx2[x]=0; } void solve() { read(k);cnt=0;int top=0,used=0; for(int i=1,x;i<=k;i++) read(x),tag[x]++,in[++cnt]=x,vis[x]=1; /// build sort(in+1,in+cnt+1,cmp);cnt=unique(in+1,in+cnt+1)-in-1; sta[++top]=1,use[++used]=1; for(int i=1;i<=cnt;i++) { if(in[i]==1) continue; int t=T.lca(in[i],sta[top]),pre=-1; while(dfn[sta[top]]>dfn[t]&&dfn[sta[top]]<dfn[t]+sz[t]-1) { if(pre!=-1) ins(sta[top],pre,dep[pre]-dep[sta[top]]); pre=sta[top],use[++used]=sta[top];top--; } if(pre!=-1) ins(t,pre,dep[pre]-dep[t]); if(sta[top]!=t) sta[++top]=t; sta[++top]=in[i]; } int pre=-1; while(top) { if(pre!=-1) ins(sta[top],pre,dep[pre]-dep[sta[top]]); use[++used]=sta[top],pre=sta[top];top--; } /// ans=0,Min=1e9,Max=0;dfs(1,0); //printf("%lld %d %d\n",ans,Min,Max); write(ans,' '); write(Min,' '); write(Max,'\n'); for(int i=1;i<=used;i++) head[use[i]]=tag[use[i]]=vis[use[i]]=0; } }VT; int main() { read(n);for(int i=1,x,y;i<n;i++) read(x,y),T.ins(x,y); dep[0]=-1;T.dfs(1,0);int t;read(t); while(t--) VT.solve(); flush(); return 0; }
[bzoj3611] [HEOI2014]大工程