当前位置: 首页 > news >正文

苏州网站开发公司电话青岛北方现货交易平台代理

苏州网站开发公司电话,青岛北方现货交易平台代理,ps网页设计稿,便宜建网站题目 给你一张 n n n 个点 m m m 条边的无向图,有 p p p 个关键点。你需要选择 k k k 个点染黑,使得这 p p p 个关键点到这 k k k 个黑点的代价和最小。定义代价为两点之间边权最大的边的最小值。 你需要求出 k 1,2,…,n 的所有答案 E1 n,m,p&l…

题目

给你一张 n n n 个点 m m m 条边的无向图,有 p p p 个关键点。你需要选择 k k k 个点染黑,使得这 p p p 个关键点到这 k k k 个黑点的代价和最小。定义代价为两点之间边权最大的边的最小值。
你需要求出 k = 1,2,…,n 的所有答案

E1 n,m,p<=400
E2 n,m,p<=5000
E3 n,m,p<=2e5

传送门

E1 & E2

两点之间最大边权最小值让你想到了什么?最小生成树。
但是这玩意直接在最小生成树上也不好做啊。但是如果是 kruskal 重构树呢?
显然,两个点 ( u , v ) (u,v) (u,v) 之间的代价就是重构树上的 v a l l c a ( u , v ) val_{lca(u,v)} vallca(u,v)
这样我们就可以愉快的dp啦!

d p u , i dp_{u,i} dpu,i 为以 u u u 为根的子树,染黑了 i i i 个关键点的最小代价。
转移要讨论这棵树有没有染黑任何一个点,如果没有的话整棵树的代价就是 s i z × v a l siz\times val siz×val,其中 s i z siz siz 为子树内关键点的个数。
做个树上背包就行啦。时间复杂度 O ( n 2 ) O(n^2) O(n2)

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+7,inf=1e18,mod=998244353;
int n,m,k;
vector<bool> bz;
vector<int> val,fa,siz;
vector<vector<int>> e,dp;
int gf(int x)
{return x==fa[x]?x:fa[x]=gf(fa[x]);
}
void dfs(int u,int fa)
{dp[u].assign(1,inf);if(bz[u]){siz[u]=1;dp[u].push_back(0);}for(auto v:e[u]){if(v==fa) continue;dfs(v,u);vector<int> dpn(siz[u]+siz[v]+1,inf);for(int i=1; i<=siz[u]+siz[v]; i++){for(int j=max(0ll,i-siz[u]); j<=min(i,siz[v]); j++){if(j==0){dpn[i]=min(dpn[i],dp[u][i-j]+val[u]*siz[v]);}else if(i==j){dpn[i]=min(dpn[i],dp[v][j]+val[u]*siz[u]);}else{dpn[i]=min(dpn[i],dp[u][i-j]+dp[v][j]);}}}siz[u]+=siz[v];dp[u]=dpn;}
}
void O_o()
{cin>>n>>m>>k;bz.assign(2*n,0);for(int i=1; i<=k; i++){int x;cin>>x;bz[x]=1;}vector<array<int,3>> edge;//l,x,yfor(int i=1; i<=m; i++){int x,y,l;cin>>x>>y>>l;edge.push_back({l,x,y});}sort(edge.begin(),edge.end());fa.assign(2*n,0);for(int i=1; i<=2*n; i++) fa[i]=i;int rt=n;e.assign(2*n,vector<int>());val.assign(2*n,0);for(auto [l,x,y]:edge){int u=gf(x),v=gf(y);if(u==v) continue;rt++;fa[u]=rt;fa[v]=rt;val[rt]=l;e[rt].push_back(u);e[rt].push_back(v);}dp.assign(2*n,vector<int>());siz.assign(2*n,0);dfs(rt,0);for(int i=1; i<=min(k,n); i++)cout<<dp[rt][i]<<" ";for(int i=k+1; i<=n; i++)cout<<"0 ";cout<<"\n";
}
signed main()
{ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);cout<<fixed<<setprecision(12);int T=1;cin>>T;while(T--){O_o();}
}

这个树上背包似乎很难继续优化了呢。我们必须从题目更深的性质去思考问题。
在解决 E3 之前,我们不妨先看一下这道题:

CCPC2024 山东邀请赛 F

在这里插入图片描述
这是一道签到题。
可以发现,这个式子可以拆成 k k k 段后缀和之和,并且其中一段后缀和必须是整个序列。
所以直接把后缀和排个序,选出前 k − 1 k-1 k1 大的后缀和,再加上整个序列的和即可。

E3

在题目中,一个点都不染色是不合法的,代价应该为 i n f inf inf,但这不利于我们解题。
我们不妨假设他们每一条路径都经过了最大的那条边,也就是初始答案 a n s = s i z r t ∗ v a l r t ans=siz_{rt}*val_{rt} ans=sizrtvalrt
把样例的重构树画出来,观察一下染黑了一个叶子,对答案会有什么影响?
不太好看出来?由那道签到题的启发,给 v a l val val 做个树上差分试试?
可以发现,从叶子结点到根的那条路径上, v a l f a − v a l u val_{fa}-val_{u} valfavalu 的计算次数都被减少了 s i z u siz_u sizu
再染一个点试试?可以发现,从叶子结点,一直到已经被选择过的那条链为止, v a l f a − v a l u val_{fa}-val_{u} valfavalu 的计算次数都被减少了 s i z u siz_u sizu
问题就转换成了,你要在树上选出减少答案前 k k k 大,互不相交的链。
是不是很像树链剖分?
没错,我们把 ( v a l f a − v a l u ) ∗ s i z u (val_{fa}-val_{u})*siz_u (valfavalu)sizu 作为 ( u , f a u ) (u,fa_u) (u,fau) 的边权,对整棵树做长链剖分(jiangly:这是典中典长链剖分题)。
把所有的长链的权值排序,然后每次选出前 k k k 大减去就做完啦!

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+7,inf=1e18,mod=998244353;
int n,m,k;
vector<bool> bz;
vector<int> val,fa,siz,p;
vector<vector<int>> e;
int gf(int x)
{return x==fa[x]?x:fa[x]=gf(fa[x]);
}
int dfs(int u,int fa)
{if(bz[u]){siz[u]=1;}int mx=0;for(auto v:e[u]){int res=dfs(v,u);siz[u]+=siz[v];if(mx<res)swap(res,mx);p.push_back(res);}if(fa!=0)mx+=siz[u]*(val[fa]-val[u]);return mx;
}
void O_o()
{cin>>n>>m>>k;bz.assign(2*n,0);for(int i=1; i<=k; i++){int x;cin>>x;bz[x]=1;}vector<array<int,3>> edge;//l,x,yfor(int i=1; i<=m; i++){int x,y,l;cin>>x>>y>>l;edge.push_back({l,x,y});}sort(edge.begin(),edge.end());fa.assign(2*n,0);for(int i=1; i<=2*n; i++) fa[i]=i;int rt=n;e.assign(2*n,vector<int>());val.assign(2*n,0);for(auto [l,x,y]:edge){int u=gf(x),v=gf(y);if(u==v) continue;rt++;fa[u]=rt;fa[v]=rt;val[rt]=l;e[rt].push_back(u);e[rt].push_back(v);}siz.assign(2*n,0);p.clear();p.push_back(dfs(rt,0));int ans=k*val[rt];sort(p.begin(),p.end(),greater<>());for(int i=0; i<n; i++){ans-=p[i];cout<<ans<<" ";}cout<<"\n";
}
signed main()
{ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);cout<<fixed<<setprecision(12);int T=1;cin>>T;while(T--){O_o();}
}
http://www.yayakq.cn/news/606430/

相关文章:

  • 网站备案目的正规十大电商平台
  • 电商企业网站建设方案深圳百度国际大厦
  • 金融网站建设方案ppt亚洲杯中国菲律宾
  • 河北手机版建站系统开发免费做qq互赞网站
  • 寮步镇网站建设电商有多少种方法推广
  • 平面设计公司网站建设费用建设教育网站
  • 企业网站管理的含义及内容erlang做网站优势
  • 柳州柳北建设局网站邯郸网络技术公司
  • 教育响应式网站建设火星人网页设计培训
  • 福建省住房城乡和城乡建设厅网站模板做的网站不好优化
  • 网站建设的流程电子商务百度申请qq号免费注册
  • 怎样注册一个网站平台解压wordpress路径的权限
  • 外语网站建设义乌网站建设方案详细
  • 石家庄做网站制作公司wordpress图片中文
  • 网站开发高级证登陆网站空间的后台
  • 广东省企网站建设交流建设网站
  • 西安外贸网站建设wordpress怎么分页
  • 成都网站建设推广详情wordpress 支付宝接入
  • 建设网站电脑配置设计师个人网站主页
  • 电脑做apk的网站h5天河网站设计
  • 眉山网站优化公众号平台文章wordpress
  • 上海的外贸网站建设公司价格徐州招聘网最新招聘
  • 网站建设前准备潍坊专科学校
  • 物流系统网站策划书东莞高端建站公司
  • 优化网站内容的方法wordpress实现选项卡
  • 做美妆网站的关键词网站开发工程师考试
  • 保定的网站建设网站建设设计制作
  • 企业手机版网站杭州维利国德网站建设案例
  • 南京网站制作公司排名前十seo是什么意思职业
  • 金乡做网站 亿九自己做网站需要学些什么