【2018/10/19测试T3】比特战争

【题目】

内网传送门
外网传送门

【分析】

30 pts:

枚举每条边的占领情况然后判断即可,复杂度 O ( 2 m ) (2^m) (2m)

70 pts:

最后被占领的桥以及桥联通的点一定形成若干联通块。

注意到一个联通块内部的答案为 m a x ( m a x    a i , m a x    c i ) ∗ m i n    b i max(max \;a_i,max\;c_i)∗min \;b_i max(maxai,maxci)minbi

考虑按 c c c 从小到大加入每条边,加入一条边的时候若两端已经联通,那么这条边肯定没用了,于是最后的图形成了若干棵生成树。可以分开计算答案。

直接暴力树形 D P DP DP,记 f i , j , k f_{i,j,k} fi,j,k i i i 的子树中,与 i i i 联通的权值最大为 j j j,最小为 k k k 的最小花费。

因为可能的值只有 O ( n ) (n) (n) 个,所以状态数是 O ( n 3 ) (n^3) (n3) 的。

合并两个子树的答案需要 O ( n 4 ) (n^4) (n4) 的时间,总的时间为 O ( n 5 ) (n^5) (n5)

100 pts:

可以证明,最优方案一定是生成最小生成树过程中的某个阶段。

于是我们做最小生成树的时候维护一下联通块的最大最小值和最优答案,合并的时候更新一下答案就好了。

时间复杂度 O ( ( m + n ) ∗ l o g    n ) ((m+n)*log\;n) ((m+n)logn)

【代码】

#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 100005
#define M 200005
using namespace std;
int a[N],b[N],father[N];
long long val[N],Max[N],Min[N];
struct edge
{
	int u,v,w;
}e[M];
int find(int x)
{
	if(father[x]!=x)
	  father[x]=find(father[x]);
	return father[x];
}
bool comp(const edge &p,const edge &q)
{
	return p.w<q.w;
}
int main()
{
//	freopen("bit.in","r",stdin);
//	freopen("bit.out","w",stdout);
	int n,m,i,x,y;
	long long sum=0;
	scanf("%d%d",&n,&m);
	for(i=1;i<=n;++i)
	{
		father[i]=i;
		scanf("%d%d",&a[i],&b[i]);
		Max[i]=a[i],Min[i]=b[i];
		val[i]=a[i]*b[i],sum+=val[i];
	}
	long long ans=sum;
	for(i=1;i<=m;++i)
	  scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
	sort(e+1,e+m+1,comp);
	for(i=1;i<=m;++i)
	{
		x=find(e[i].u);
		y=find(e[i].v);
		if(x==y)  continue;
		father[x]=y;
		val[y]+=val[x];
		Min[y]=min(Min[x],Min[y]);
		Max[y]=max(max(Max[x],Max[y]),1ll*e[i].w);
		sum-=val[y];val[y]=min(val[y],1ll*Min[y]*Max[y]);sum+=val[y];
		ans=min(ans,sum);
	}
	printf("%lld",ans);
//	fclose(stdin);
//	fclose(stdout);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值