来自FallDream的博客,未经允许,请勿转载,谢谢。

小N最近在研究NP完全问题,小O看小N研究得热火朝天,便给他出了一道这样的题目:
有 n 个球,用整数 1 到 n 编号。还有 m 个筐子,用整数1到m编号。
每个球只能放进特定的两个筐子之一,第 i 个球可以放进的筐子记为 Ai 和 Bi 。
每个球都必须放进一个筐子中。
如果一个筐子内有奇数个球,那么我们称这样的筐子为半空的。
求半空的筐子最少有多少个。
小N看到题目后瞬间没了思路,站在旁边看热闹的小I嘿嘿一笑:"水题!"
然后三言两语道出了一个多项式算法。
小N瞬间就惊呆了,三秒钟后他回过神来一拍桌子:
"不对!这个问题显然是NP完全问题,你算法肯定有错!"
小I浅笑:"所以,等我领图灵奖吧!"
小O只会出题不会做题,所以找到了你--请你对这个问题进行探究,并写一个程序解决此题
 
n,m<=200000
感觉是一道智商题 所以来做了做
想了半天只会一个log的做法
考虑线性基 每次有一个球可以选择a,b(a<b),就先把a的权值塔上1,然后加入只有a和b位是1的线性基
直接暴力插入是n^2,但是发现一个点出发的很多条边,在选择了一个基之后,假设基是u->v,那么u->其他点的边都变成了v->其他点的边,所以可并堆维护即可,复杂度nlogn
当然只有这道题才能满足线性基贪心
 
然后去搜了搜题解,发现答案就是有奇数条边的联通块个数 
因为偶数条边一定能满足两两配对 应该是可以证明的吧
所以直接dfs就行了 复杂度O(n)
线性基+可并堆
#include<iostream>
#include<cstdio>
#include<queue>
#define INF 2000000000
#define Dis(x) (x?x->dis:0)
#define MN 200000
using namespace std;
inline int read()
{
int x = , f = ; char ch = getchar();
while(ch < '' || ch > ''){ if(ch == '-') f = -; ch = getchar();}
while(ch >= '' && ch <= ''){x = x * + ch - '';ch = getchar();}
return x * f;
} int n,m,s[MN+],to[MN+],ans=;
struct Tree
{
Tree *l,*r;int dis,x;
Tree(int k){dis=;x=k;l=r=NULL;}
int top(){return x;}
friend Tree* Merge(Tree*a,Tree*b)
{
if(!a) return b;
if(!b) return a;
if(a->x>b->x) swap(a,b);
a->r=Merge(a->r,b);
if(Dis(a->l)<Dis(a->r)) swap(a->l,a->r);
a->dis=Dis(a->r)+;
return a;
}
Tree* pop(){return Merge(l,r);}
Tree* ins(int x){return Merge(new Tree(x),this);}
}*rt[MN+]; int main()
{
m=read();n=read();
for(int i=;i<=n;i++) s[i]=,rt[i]=new Tree(INF);
for(int i=;i<=m;++i)
{
int x=read(),y=read();
if(x>y) swap(x,y);
s[x]^=;rt[x]=rt[x]->ins(y);
}
for(int i=;i<=n;++i)
{
while(rt[i]->top()==i) rt[i]=rt[i]->pop();
int x=rt[i]->top();
if(x==INF) continue;
to[i]=x;
rt[x]=Merge(rt[x],rt[i]);
}
for(int i=;i<=n;++i)
{
if(to[i]&&!s[i]) s[i]^=,s[to[i]]^=;
ans+=s[i];
}
cout<<n-ans<<endl;
return ;
}

靠谱做法

#include<iostream>
#include<cstdio>
#define getchar() (*S++)
#define MN 200000
char B[<<],*S=B;
using namespace std;
inline int read()
{
int x = ; char ch = getchar();
while(ch < '' || ch > '') ch = getchar();
while(ch >= '' && ch <= ''){x = x * + ch - '';ch = getchar();}
return x;
} int head[MN+],ans=,sum=,cnt=,n,m;
struct edge{int to,next,w;}e[MN*+];
bool mark[MN+]; inline void ins(int f,int t)
{
e[++cnt]=(edge){t,head[f]};head[f]=cnt;
e[++cnt]=(edge){f,head[t]};head[t]=cnt;
} void dfs(int x)
{
mark[x]=;
for(int i=head[x];i;i=e[i].next,++sum)
if(!mark[e[i].to]) dfs(e[i].to);
} int main()
{
fread(B,,<<,stdin);
m=read();n=read();
for(register int i=;i<=m;++i) ins(read(),read());
for(register int i=;i<=n;++i)if(!mark[i])
{
sum=;dfs(i);
ans+=((sum/)&);
}
cout<<ans;
return ;
}

[bzoj4874]筐子放球的更多相关文章

  1. bzoj 4874: 筐子放球

    4874: 筐子放球 Time Limit: 10 Sec  Memory Limit: 256 MB Description 小N最近在研究NP完全问题,小O看小N研究得热火朝天,便给他出了一道这样 ...

  2. 【bzoj4272】筐子放球

    看题解会的系列…… 详细解释先坑着,以后补…… #include<bits/stdc++.h> #define N 200005 using namespace std; ,tot=,cn ...

  3. 放球游戏B

    题目描述 校园里在上活动课,Red和Blue两位小朋友在玩一种游戏,他俩在一排N个格子里,自左到右地轮流放小球,每个格子只能放一个小球.第一个人只能放1个球,之后的人最多可以放前一个人的两倍数目的球, ...

  4. 【题解】放球游戏B

    题目描述 校园里在上活动课,Red和Blue两位小朋友在玩一种游戏,他俩在一排N个格子里,自左到右地轮流放小球,每个格子只能放一个小球.第一个人只能放1个球,之后的人最多可以放前一个人的两倍数目的球, ...

  5. 【题解】放球游戏A

    题目描述 校园里在上活动课,Red和Blue两位小朋友在玩一种游戏,他俩在一排N个格子里,自左到右地轮流放小球,每个格子只能放一个小球.每个人一次只能放1至5个球,最后面对没有空格而不能放球的人为输. ...

  6. COGS396. [网络流24题]魔术球问题(简化版

    问题描述: 假设有n根柱子,现要按下述规则在这n根柱子中依次放入编号为 1,2,3,4......的球. (1)每次只能在某根柱子的最上面放球. (2)在同一根柱子中,任何2个相邻球的编号之和为完全平 ...

  7. C#之桶中取黑白球问题

    <编程之美>284页,问题4.6:桶中取黑白球. 有一个桶,里面有白球.黑球各100个,人们必须按照以下规则把球取出来: 1. 每次从桶中拿两个球: 2. 如果两球同色,再放入一个黑球: ...

  8. cogs_396_魔术球问题_(最小路径覆盖+二分图匹配,网络流24题#4)

    描述 http://cojs.tk/cogs/problem/problem.php?pid=396 连续从1开始编号的球,按照顺寻一个个放在n个柱子上,\(i\)放在\(j\)上面的必要条件是\(i ...

  9. 【网络流24题】No.4 魔术球问题 (二分+最小路径覆盖)

    [题意] 假设有 n 根柱子, 现要按下述规则在这 n 根柱子中依次放入编号为 1, 2, 3, ¼的球.( 1)每次只能在某根柱子的最上面放球.( 2)在同一根柱子中,任何 2 个相邻球的编号之和为 ...

随机推荐

  1. HTML 样式设计

    1.自动设置外边距 style="margin:auto auto;"

  2. mysql5.5中datetime默认值不能为NOW或者CURRENT_TIMESTAMP,用触发器解决

    mysql5.6及以上的版本datatime默认值可以为CURRENT_TIMESTAMP或者NOW 那我们要用的是mysql5.5及以下版本呢? 请看代码 delimiter // DROP TRI ...

  3. DOM中的事件对象(event)

    在触发DOM上的某个事件时,会产生一个事件对象event,这个对象中包含着所有与事件相关的信息. 包括导致事件的元素.事件的类型以及其他与特定事件相关的信息. 例如:鼠标操作导致的事件对象中,会包含鼠 ...

  4. 【深度学习】深入理解Batch Normalization批标准化

    这几天面试经常被问到BN层的原理,虽然回答上来了,但还是感觉答得不是很好,今天仔细研究了一下Batch Normalization的原理,以下为参考网上几篇文章总结得出. Batch Normaliz ...

  5. Gson序列化对象如何忽略字段

    Gson序列化对象如何忽略字段 Gson版本 2.8.2 梗概 用注解@Expose(serialize = false, deserialize = false)在类的成员上以告诉Gson 跳过本字 ...

  6. httpClient解决post请求重定向的问题

    import com.dadi.saas.util.HTTPUtils; import org.apache.commons.httpclient.Header; import org.apache. ...

  7. 新概念英语(1-35)Our village

    新概念英语(1-35)Our village Are the children coming out of the park or going into it ? This is a photogra ...

  8. python入门(11)条件判断和循环

    python入门(11)条件判断和循环 条件判断 计算机之所以能做很多自动化的任务,因为它可以自己做条件判断. 比如,输入用户年龄,根据年龄打印不同的内容,在Python程序中,用if语句实现: ag ...

  9. leetcode算法: Find All Duplicates in an Array

    Given an array of integers, 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and others ...

  10. PHP / Laravel 月刊 #23

    最新资讯 Laravel 5.6 中文文档翻译完成,译者 60 人,耗时 10 天 Summer Dingo API 中文文档翻译召集[已完成] Summer 我最喜欢 Laravel 5.6 的三个 ...