Codeforces Round#586

D Alex and Julian
题意:已知集合B,可以把|i-j|属于B的点连一条线构成图。问从B中最少删多少点能使图为二分图。
无向图G为二分图的充分必要条件是:G至少有两个顶点,并且其所有回路的长度均为偶数。
将造成回路长度为奇数的点删去;
如果选中了数a,那么…,a/4,a/2,2a,4a,…都是不能选的;
即如果能够共存,它们的2的幂次数应该是一样的;
所以其实这是个数论题?
就只是用了二分图的性质
不好想啊
我是想不出来的

#pragma warning(disable:4996)
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define ll long long
const int maxn = 2e5 + 5;
ll b[maxn];
set<ll> sett[105];
int main()
{
	freopen("in.txt", "r", stdin);
	int n;
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) {
		scanf("%lld", &b[i]);
		ll temp = b[i];
		int cnt = 0;
		while (!(temp & 1)) {
			cnt++;
			temp >>= 1;
		}
		sett[cnt].insert(b[i]);
	}
	int maxindex = 0;
	int maxx = sett[0].size();
	for (int i = 1; i <= 64; i++) {
		if (maxx < sett[i].size()) {
			maxx = sett[i].size();
			maxindex = i;
		}
	}
	printf("%d\n", n-maxx);
	for (int i = 0; i <= 64; i++) {
		if (i == maxindex)continue;
		else {
			for (auto it : sett[i]) {
				printf("%lld ", it);
			}
		}
	}
}

E Tourism
题意:已知一个无向图。无自环、保证联通。每个点有一个权值。Alex可从sta点开始,使走过的点的权值和最大(每个点只能加一次),并且不可以连续通过一条边两次。

思路:可以想一想要连续通过一条边两次的情况:该边是个桥,并且点v不在环内。
所以可以用tarjan先缩个点,得到一个无环图,就是个树。要是该点是通过缩点所得那就可以重复走它连着的边,不是通过缩点所得那走过去后就不能回走了。
但是这样是错的=-=太繁琐了,codeforces的题怎么能这么麻烦的写呢?
所以正解其实是…

void dfs(int x,int fa) {
    vis[x]=1;
    for(auto v:e[x]) {
        if(v==fa) continue;
        if(vis[v]) t[x]=1;
        else dfs(v,x),t[x]|=t[v];
    }
    if(!t[x]) {
        for(auto v:e[x]) if(v!=fa) s[x]=max(s[x],s[v]);
        s[x]+=w[x];
    }
}

你可能感兴趣的:(codeforces题集)