【五校联考3day2】A

Description

帝国时代3是一款十分刺激的RTS游戏。你需要控制自己的一块殖民地,发展殖民地的经济和军事,最终打败其他殖民地。小L是这个游戏的狂热爱好者。一次小L打算打AI试试身手。
小L发展了几分钟,自己的殖民地人口便突破了30,然而小L发现大事不好了:
小L还处在不能建造军事单位的“发现时代”,然而敌人早已经到了“殖民时代”,发展起了一支雄厚的殖民地军,小L的殖民地受攻击了却没有一个正规的军事单位用来防御!不要认为这是小L 的技术问题,实际上AI还停留在以jg斗争为纲的落后理念上,而小L 早就以经济为第一要务了。
小L在之前已经在自己殖民地的外部,拉起了许多围墙。
帝国时代3里的围墙如图所示。

每一道围墙,总是连接着两个围墙连接处(以下简称“连接处”)。

现在小L有n个连接处,m道围墙}。
小L虽然没兵,但是他的智商比AI不知道高到那里去了,因此,只要每个连接处至少连接着k道围墙},小L就一定能顶住这波攻击。
小L可以任意加围墙,每道围墙可以连接两个已有的连接处。
连接处是不能连接自己的,但是这里有一些规则与原帝国时代3的设定不同,两个连接处之间可以连接多个围墙,连接处初始时可能不连任何围墙,围墙之间也可以相交。
小L想知道,自己至少要多加多少道围墙}才能满足每个连接处至少连接着k道围墙?

Input

第一行三个整数n, m, k,表示连接处个数、围墙个数以及每个连接处至少要连接的围墙个数,连接处被编号为1到n}。
接下来m行,每行两个正整数x, y,表示这个围墙连接编号为x的连接处和编号为y的连接处。

Output

输出一行一个整数,表示至少要加的围墙的条数。

Sample Input

输入1:
2 0 1
输入2:
5 4 2
1 2
2 5
4 3
3 1
输入3:
4 3 2
1 2
2 3
1 2
输入4:
5 11 7
1 3
4 2
1 5
4 2
2 5
1 3
4 1
2 3
4 1
5 1
1 5

Sample Output

输出1:
1
样例1解释:初始时有两个连接处,题目中要求至少每个连接处要连1个围墙,我们加一个围墙连接这两个连接处即可。
输出2:
1
样例2解释:连接编号为5的和编号为4的连接处即可。
输出3:
2
样例3解释:编号为4的连接处没有连接任何围墙,编号为3的连接处还需要一条。连接编号为4的和编号为3的连接处之后,编号为4的连接处与另外三个连接处中任意一个连一个围墙即可,注意连接处是不能自己和自己连接的。
输出4:
7

Data Constraint

对于60%的数据,n × ans ≤ 10000000,ans表示最终的答案。
对于前100%的数据,n, m, k ≤ 100000,n ≥ 2, m, k ≥ 0, x ≠ y, 1 ≤ x, y ≤ n。

Source / Author: 雅礼中学 毛啸 A

 

题解:

考虑贪心。

如果有点还少了边,肯定是把后来加上的边的一端,连上当前需求最多的边,另一端往后连。

发现,这时答案可以直接计算。

设一开始需求边数最多的点u 要tot个,其余的点需求的总和为need

这时有两种情况。

  1. 若tot > need,连完need条边后除u其他点都够了k,其余的边一端为u,另一端随意。ans = tot
  2. 若tot <= need,答案是\left \lceil \frac{tot+need}{2} \right \rceil,除2的原因是没加入一条边,可以贡献两个点,上取整的原因是若tot + need为奇数,还需多加上一条才能满足
    #include<bits/stdc++.h>
    #define N 100010
    #define inf 2147483647
    #define rint register ll
    #define ll long long
    #define point(a) multiset<a>::iterator 
    #define mod (ll)(1e9+7)
    #define mem(a,b) memset(a,b,sizeof (a))
    #define open(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout);
    using namespace std;
    
    
    ll n,m,k,r[N],tot,ans,t,i,need;
    
    int main()
    {
    	open("wall");
    	scanf("%lld%lld%lld",&n,&m,&k);
    	for(i=1;i<=m;i++)
    	{
    		ll u,v;
    		scanf("%lld%lld",&u,&v);
    		r[u]++;
    		r[v]++;
    	}
    	sort(r+1,r+1+n);
    	for(i=2;i<=n;i++)need+=max(k-r[i],0ll);
    	if(k-r[1] > need)
    	{
    		printf("%lld",k-r[1]);
    		return 0;
    	}
    	need+=k-r[1];
    	printf("%lld",(ll)ceil((double)need/2));
    	return 0;
    }

    时间复杂度:O(n)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值