2021牛客暑期多校训练营6-J题

J题:Defend Your Country

原题

题目大意

请添加图片描述

solution

先讨论几种情况。

  • 当n为偶数,则不需要删去任何的边,直接输出所有点的权值总和。(①)
  • 当n为奇数,最简单的想法就是分成偶数和奇数的子图,并使奇数子图权值最小,而最理想的的情况是分出一个权值最小的点。设这个点为x。
    • x不是割点,则将x单独后分开剩下的图仍联通且为偶数。(②)
    • x是割点,所有与x联通的子图在分割后点的个数均为偶数。(③)
    • x是割点,所有与x联通的子图中存在个数为奇数(④)

在上述几种情况中①可以直接输出。
然后我们猜想在n为奇数是否只需分割出1个点。
假设删去3个(或更多)点
在这里插入图片描述
在三个点构成的连通块上可以分割出偶数的更小连通块,而分割出单独点的权值必然小于整个块,最后只需分出一个点。
∴ \therefore ②③两种情况都可以将x点单独分开,然后权值和为 总 权 值 − 2 × 点 x 权 值 总权值-2\times点x权值 2×x
所以n为奇数时只需遍历每个点,情况④时不合法。
然后求所有合法权值的最小值, A n s = S u m − 2 × 最 小 合 法 权 值 Ans=Sum-2\times 最小合法权值 Ans=Sum2×

c o d e \large code code

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e6+7;
int n,m,x,y,w[N],dfn[N],low[N],num[N],o;
ll sum=0;
int minn=1<<30;
vector <int > v[N];
ll read()
{
	ll num=0,f=1;
	char ch=getchar();
	while(ch>'9'||ch<'0')
	if(ch=='-'){
		f=-1;
		ch=getchar();
	}
	while(ch<='9'&&ch>='0'){
		num=num*10+ch-'0';
		ch=getchar();
	}
	return num*f;
}
void Tarjan(int x,int fa)
{
	bool flag=1;
	vector <int > ::iterator it;
	num[x]=1;
	dfn[x]=low[x]=++o;
	for(it=v[x].begin();it!=v[x].end();it++)
	{
		if(*it==fa) continue;
		if(!dfn[*it])
		{
			Tarjan(*it,x);
			low[x]=min(low[x],low[*it]);
			num[x]+=num[*it];
			if(low[*it]>=dfn[x]&&num[*it]&1)//当前点为割点,且分割完存在奇数点的联通块
				flag=0;
		}
		else
		low[x]=min(low[x],dfn[*it]);
	}
	if(flag)//更新w[x],求最小值
	minn=min(minn,w[x]);
}
int main()
{
	int T;
	T=read();
	while(T--)
	{
		n=read();m=read();
		minn=1<<30;
		sum=0;
		for(int i=1;i<=n;i++){
			w[i]=read();
			v[i].clear();
			sum+=w[i];
			dfn[i]=0;
		}
		for(int i=1;i<=m;i++){
			x=read();y=read();
			v[x].push_back(y);
			v[y].push_back(x);
		}
		if(n%2==0)
		printf("%lld\n",sum);
		else
		{
			o=0;
			Tarjan(1,0);
			printf("%lld\n",(sum-minn)-minn);
		}
	}
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值