codeforces 553 D Nudist Beach

题意大概是,给出一个图,保证每个点至少有一条边以及任意两点间最多一条边。很显然这个图有众多点集,若我们给每个点定义一个权值,那每个点集都有一个最小权值点,现在要求出一个点集,这个点集的最小权值点尽可能的大。

某个子集中,点的权值是这样算的,在该子集中这个点的度除以该点在图中的度。

乍看上去似乎无从下手。

可以显然知道的是,每个点在图中的权值是很容易算出来的,那我们尝试从图中进行删点,使得当前图的最小权值点的权值变大,显然可以知道要删除最小权值点,为什么呢?因为若删除次小权值点,若次小权值点跟最小权值点有连边,那最小权值点还是新图的最小权值点。若没有连边,那新图的最小权值点也依旧未变。所以只有删除最小权值点才有可能改变新图的最小权值点,也只有这样能让新图的最小权值发生改变。那么到这里就十分明显了,只要每次删除当前图的最小权值点,那么必然可以枚举出一个新图,这个新图的点构成的点集正是我们要的答案。

于是这个题就可以做了,我是直接做了两次删除,第一次得出最大最小权值是多少,第二次枚举到一个新图的最小权值等于最大最小权值,那么很显然这个新图的子集就是答案。

维护一个小堆就好了,时间复杂度是2(n+m)log(n+m)

#include<map>
#include<string>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<queue>
#include<vector>
#include<iostream>
#include<algorithm>
#include<bitset>
#include<climits>
#include<list>
#include<iomanip>
#include<stack>
#include<set>
using namespace std;
struct node
{
	int no;
	double val;
	node(){}
	node(int no,double val)
	{
		this->no=no;
		this->val=val;
	}
	bool operator <(node one)const
	{
		return val>one.val;
	}
};
priority_queue<node>q[2];
bool fb[100010],dl[100010];
vector<int>edge[100010];
int d[100010][2],dd[100010];
int main()
{
	int n,m,k;
	cin>>n>>m>>k;
	int sum=k;
	while(k--)
	{
		int t;
		cin>>t;
		fb[t]=1;
	}
	while(m--)
	{
		int a,b;
		cin>>a>>b;
		d[a][0]++;
		d[b][0]++;
		if(!fb[a])
			d[b][1]++;
		if(!fb[b])
			d[a][1]++;
		edge[a].push_back(b);
		edge[b].push_back(a);
	}
	double mn=1e99;
	for(int i=1;i<=n;i++)
		if(!fb[i])
		{
			q[0].push(node(i,double(d[i][1])/d[i][0]));
			mn=min(mn,double(d[i][1])/d[i][0]);
		}
	q[1]=q[0];
	int flag=0;
	for(int i=0;i<2;i++)
	{
		memset(dl,0,sizeof(dl));
		memset(dd,0,sizeof(dd));
		if(i==1&&flag==0)
			break;
		while(q[i].size())
		{
			node t=q[i].top();
			q[i].pop();
			if(dl[t.no])
				continue;
			if(i==1)
			{
				if(t.no==flag)
					break;
				sum++;
			}
			dl[t.no]=1;
			if(i==0&&t.val>mn)
			{
				mn=t.val;
				flag=t.no;
			}
			for(int j=0;j<edge[t.no].size();j++)
			{
				int v=edge[t.no][j];
				if(dl[v]||fb[v])
					continue;
				dd[v]++;
				q[i].push(node(v,double(d[v][1]-dd[v])/d[v][0]));
			}
		}
	}
	cout<<n-sum<<endl;
	for(int i=1;i<=n;i++)
		if(!fb[i]&&!dl[i])
			cout<<i<<" ";
}

time limit per test

2 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

Nudist Beach is planning a military operation to attack the Life Fibers. In this operation, they will attack and capture several cities which are currently under the control of the Life Fibers.

There are n cities, labeled from 1 to n,
and m bidirectional roads between them. Currently, there are Life Fibers in every city. In addition, there are k cities
that are fortresses of the Life Fibers that cannot be captured under any circumstances. So, the Nudist Beach can capture an arbitrary non-empty subset of cities with no fortresses.

After the operation, Nudist Beach will have to defend the captured cities from counterattack. If they capture a city and it is connected to many Life Fiber controlled cities, it will be easily defeated. So, Nudist Beach would like to capture a set of cities
such that for each captured city the ratio of Nudist Beach controlled neighbors among all neighbors of that city is as high as possible.

More formally, they would like to capture a non-empty set of cities S with no fortresses of Life Fibers. The strength of a city  is
defined as (number of neighbors of x in S)
/ (total number of neighbors of x). Here, two cities are called neighbors if they are connnected with a road. The goal is to maximize
the strength of the weakest city in S.

Given a description of the graph, and the cities with fortresses, find a non-empty subset that maximizes the strength of the weakest city.

Input

The first line of input contains three integers n,?m,?k (2??≤??n??≤?100?000, 1?≤?m?≤?100?000, 1?≤?k?≤?n?-?1).

The second line of input contains k integers, representing the cities with fortresses. These cities will all be distinct.

The next m lines contain the roads. The i-th
of these lines will have 2 integers ai,?bi (1?≤?ai,?bi?≤?nai?≠?bi).
Every city will have at least one road adjacent to it.

There is no more than one road between each pair of the cities.

Output

The first line should contain an integer r, denoting the size of an optimum set (1?≤?r?≤?n?-?k).

The second line should contain r integers, denoting the cities in the set. Cities may follow in an arbitrary order. This line should
not contain any of the cities with fortresses.

If there are multiple possible answers, print any of them.

Sample test(s)

input

9 8 4
3 9 6 8
1 2
1 3
1 4
1 5
2 6
2 7
2 8
2 9

output

3
1 4 5

input

10 8 2
2 9
1 3
2 9
4 5
5 6
6 7
7 8
8 10
10 4

output

8
1 5 4 8 10 6 3 7

Note

The first example case achieves a strength of 1/2. No other subset is strictly better.

The second example case achieves a strength of 1. Note that the subset doesn‘t necessarily have to be connected.

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-11 06:33:48

codeforces 553 D Nudist Beach的相关文章

Codeforces 553D Nudist Beach(图论,贪心)

Solution: 假设已经选了所有的点. 如果从中删掉一个点,那么其它所有点的分值只可能减少或者不变. 如果要使若干步删除后最小的分值变大,那么删掉的点集中肯定要包含当前分值最小的点. 所以每次删掉一个点都记录一次最大值.取最大的情况输出就好. #include <bits/stdc++.h> using namespace std; const int N = 100009; vector<int> E[N], out; set<pair<double, int&g

codeforces 553 A Kyoya and Colored Balls

这个题,比赛的时候一直在往dp的方向想,但是总有一个组合数学的部分没办法求, 纯粹组合数学撸,也想不到办法-- 其实,很显然.. 从后往前推,把第k种颜色放在最后一个,剩下的k球,还有C(剩余的位置,k球的总数目-1)种放法 然后讨论第k-1种...推下去就好了 但是当时没想到-- 这里要求组合数,由于比较大,用乘法逆元... 当然直接套lucas也是可以的.... time limit per test 2 seconds memory limit per test 256 megabytes

Codeforces 599C Day at the Beach(想法题,排序)

C. Day at the Beach One day Squidward, Spongebob and Patrick decided to go to the beach. Unfortunately, the weather was bad, so the friends were unable to ride waves. However, they decided to spent their time building sand castles. At the end of the

Codeforces Round #553 (Div. 2) C题

题目网址:http://codeforces.com/contest/1151/problem/C 题目大意:给定奇数集和偶数集,现构造一个数组,先取奇数集中一个元素1,再取偶数集二个元素2,4,再取奇数集四个元素3,5,7,9,再取偶数集八个元素,6,8,10…… 得到 1,2,4,3,5,7,9,6,8,10,12……问这个数组的某一区间和是多少,并对1e9+7取模. 题解:对于奇数集x和偶数集y的前k项,有x=k^2,y=k*(k+1),首先,计算区间和,可以用前缀和,当计算前n项的和时,

Codeforces Round #553 (Div. 2) B题

题目网址:http://codeforces.com/contest/1151/problem/B 题目大意:给定一个n*m的矩阵,问是否可以从每一行中选择一个数,使得这n个数异或大于0,如果可以还要输出它们的列位置 题解:首先如果a^b==0,b!=c,则a^c>0.那么考虑构造,为了方便,选取第一列的数,如果异或>0,直接输出列位置,反之则随便在一行中,找到一个与第一个不相等的数,那么由异或性质满足条件,如果n行都找不到,则无法实现. 1 #include<bits/stdc++.h

CodeForces 599C Day at the Beach

预处理一下i到n的最小值. #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; int n; int a[100000+10]; int Min[100000+10]; int ans; int main() { scanf("%d",&n); for(int i=1;i<=n;i++) sca

Codeforces Round #553 B. Dima and a Bad XOR

题面: 传送门 题目描述: 题意很简单:在一个N*M的矩阵中(N行M列),问是否可以:每行选一个整数,使他们的异或和大于0.如果不可以,输出"NIE":如果可以,输出"TAK",并输出选择的整数. 题目分析: 这道题刚开始想直接暴力,但看到复杂度竟然是O(500^500),就怂了??.到后面仔细观察,发现题目有个数据:每个数小于1024,也就是2^10次方.会不会跟数位有关?后面分析了一下,果然是,但没时间做了??,不过结束后还是A出来了. 异或(求大佬无视):转化

codeforces 的20道C题

A - Warrior and Archer CodeForces - 595C n  偶数  然后n个数字 A B 轮流取一个 A让差变小B让差变大 直到最后2 个   求的是最小剩下的差 最后剩下的 L R  相距 n/2    求一下最小的就行 #include <iostream> #include <cstdio> #include <cmath> #include <map> #include <algorithm> #include

Codeforces Round #300-Cutting Banner(substr函数的应用)

Cutting Banner Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Submit Status Description A large banner with word CODEFORCES was ordered for the 1000-th onsite round of Codeforcesω that takes place on the Miami beach. Un