BZOJ3611: [Heoi2014]大工程
生活随笔
收集整理的這篇文章主要介紹了
BZOJ3611: [Heoi2014]大工程
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題解:虛樹模板題 維護虛樹 跑樹dp即可
/**************************************************************Problem: 3611User: c20161007Language: C++Result: AcceptedTime:15176 msMemory:357336 kb ****************************************************************/#include <bits/stdc++.h> #define ll long long const int MAXN=1e6+10; using namespace std; const ll inf=1e18; vector<int>vec[MAXN]; int f[MAXN][21];ll sum[MAXN][21];int dep[MAXN]; int p[MAXN],cnt; int st[MAXN],tot; vector<int>V; ll read(){ll x=0,f=1;char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(isdigit(ch))x=x*10+ch-'0',ch=getchar();return f*x; } void dfs(int v,int pre,int deep){dep[v]=deep;f[v][0]=pre;p[v]=++cnt;for(int i=0;i<vec[v].size();i++){int u=vec[v][i];if(u!=pre){sum[u][0]=1;dfs(u,v,deep+1);}} } void dfs1(int v){for(int i=1;i<=20;i++)sum[v][i]=sum[f[v][i-1]][i-1]+sum[v][i-1],f[v][i]=f[f[v][i-1]][i-1];for(int i=0;i<vec[v].size();i++){int u=vec[v][i];if(u!=f[v][0])dfs1(u);} } int Lca(int u,int v){if(dep[u]<dep[v])swap(u,v);int tmp=dep[u]-dep[v];for(int i=0;i<=20;i++)if(tmp&(1<<i))u=f[u][i];if(u==v)return u;for(int i=20;i>=0;i--){if(f[u][i]!=f[v][i]){u=f[u][i];v=f[v][i];}}return f[u][0]; } void built(int x){V.push_back(x);if(!tot){st[++tot]=x;return ;}int lca=Lca(x,st[tot]);// cout<<lca<<" "<<x<<" "<<st[tot]<<endl;while(tot>1&&dep[lca]<dep[st[tot-1]]){vec[st[tot]].push_back(st[tot-1]);vec[st[tot-1]].push_back(st[tot]);tot--;}if(dep[st[tot]]>dep[lca]){ // cout<<lca<<"::::"<<st[tot]<<endl;vec[st[tot]].push_back(lca);vec[lca].push_back(st[tot]);tot--;V.push_back(lca);}// cout<<tot<<"====="<<endl;if(!tot||dep[lca]>dep[st[tot]])st[++tot]=lca;// cout<<st[tot]<<endl;st[++tot]=x; } ll dist(int u,int v){ll res=0;// cout<<u<<"::::::"<<v<<endl;for(int i=20;i>=0;i--){if(dep[f[u][i]]>dep[v]){res+=sum[u][i]; // cout<<u<<"::::"<<f[u][i]<<" "<<res<<endl;u=f[u][i];}}res+=sum[u][0];return res; } ll _f[MAXN],__f[MAXN],d[MAXN],_d[MAXN]; int num[MAXN]; bool vis[MAXN]; ll ans; int po; void dfs(int x,int pre){// cout<<x<<" "<<pre<<endl;__f[x]=_d[x]=inf;_f[x]=d[x]=0;if(vis[x])num[x]=1;for(int i=0;i<vec[x].size();i++){if(vec[x][i]!=pre){dfs(vec[x][i],x);num[x]+=num[vec[x][i]];ll vul=dist(vec[x][i],x);ans+=1ll*vul*num[vec[x][i]]*(po-num[vec[x][i]]);if(d[vec[x][i]]||vis[vec[x][i]]){_f[x]=max(_f[x],d[x]+d[vec[x][i]]+vul);_f[x]=max(_f[x],_f[vec[x][i]]);d[x]=max(d[x],d[vec[x][i]]+vul);__f[x]=min(__f[x],__f[vec[x][i]]);__f[x]=min(__f[x],_d[x]+_d[vec[x][i]]+vul);_d[x]=min(_d[x],_d[vec[x][i]]+vul);if(vis[x])_f[x]=max(_f[x],d[vec[x][i]]+vul),__f[x]=min(__f[x],_d[vec[x][i]]+vul);}}}if(vis[x])_d[x]=0;if(!d[x])_d[x]=0; } int n,m; bool cmp(int aa,int bb){return p[aa]<p[bb];} int main(){n=read();int u,v;for(int i=1;i<n;i++)u=read(),v=read(),vec[u].push_back(v),vec[v].push_back(u);// cout<<"sb"<<endl;dfs(1,0,0);dfs1(1);int k;for(int i=1;i<=n;i++)vec[i].clear();m=read();for(int i=1;i<=m;i++){k=read();tot=0;ans=0;po=k;for(int i=1;i<=k;i++)v=read(),V.push_back(v),vis[v]=1;sort(V.begin(),V.end(),cmp);for(int i=1;i<=k;i++)built(V[i-1]); // for(int i=tot;i>=1;i--)cout<<st[i]<<" "; // cout<<endl;while(tot>1){vec[st[tot]].push_back(st[tot-1]),vec[st[tot-1]].push_back(st[tot]);tot--;} // cout<<vec[1].size()<<" "<<vec[4].size()<<" "<<vec[5].size()<<endl; // cout<<st[tot]<<endl;dfs(st[tot],f[st[tot]][0]);printf("%lld %lld %lld\n",ans,__f[st[tot]],_f[st[tot]]);//V.clear();for(int i=0;i<V.size();i++)vec[V[i]].clear(),vis[V[i]]=0,num[V[i]]=0;V.clear();}return 0; }?
3611: [Heoi2014]大工程
Time Limit: 60 Sec??Memory Limit: 512 MBSubmit: 2194??Solved: 945
[Submit][Status][Discuss]
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
102 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 36 6 6
1 1 1
2 2 2
2 2 2
HINT
n<=1000000?
?
q<=50000并且保證所有k之和<=2*n轉載于:https://www.cnblogs.com/wang9897/p/9426446.html
總結
以上是生活随笔為你收集整理的BZOJ3611: [Heoi2014]大工程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 02-HTTP的请求方法以及响应状态码
- 下一篇: SSM框架前台传中文到后台乱码问题的解决