BZOJ4874:筐子放球

4874: 筐子放球

Time Limit: 10 Sec   Memory Limit: 256 MB
Submit: 270   Solved: 191
[ Submit][ Status][ Discuss]

Description

小N最近在研究NP完全问题,小O看小N研究得热火朝天,便给他出了一道这样的题目:
有 n 个球,用整数 1 到 n 编号。还有 m 个筐子,用整数1到m编号。
每个球只能放进特定的两个筐子之一,第 i 个球可以放进的筐子记为 Ai 和 Bi 。
每个球都必须放进一个筐子中。
如果一个筐子内有奇数个球,那么我们称这样的筐子为半空的。
求半空的筐子最少有多少个。
小N看到题目后瞬间没了思路,站在旁边看热闹的小I嘿嘿一笑:"水题!"
然后三言两语道出了一个多项式算法。
小N瞬间就惊呆了,三秒钟后他回过神来一拍桌子:
"不对!这个问题显然是NP完全问题,你算法肯定有错!"
小I浅笑:"所以,等我领图灵奖吧!"
小O只会出题不会做题,所以找到了你--请你对这个问题进行探究,并写一个程序解决此题。

Input

第一行两个整数 n,m
接下来 n 行,第 i + 1 行有两个整数 Ai , Bi ,表示第 i 个球可以放的两个筐子。保证 Ai 不等于 Bi
1 <= n,m <= 2 * 10^5,1 <= Ai,Bi <= m

Output

第一行一个整数表示半空的筐子的最小值。

Sample Input

4 3
1 2
2 3
1 3
1 2

Sample Output

0
1,3 号球都放在 1 号筐子,2,4 号球都放在 2 号筐子。

HINT

各位不妨考虑下,如果要求输出方案应该怎么写.

Source

[ Submit][ Status][ Discuss]

题解:其实我没怎么看懂QAQ  我们把筐子看作点 把求看做边 便可以认为一个具有奇数条边的连通块便是一个答案,听起来很简单吧QAQ
贴上代码:
#include<bits/stdc++.h>
#define ll long long
const int INF = 0x7fffffff;
const double eps = 1e-5;
using namespace std;
int read()
{
	int x = 0 , f = 1; char ch = getchar();
	while(ch<'0'||ch>'9') {if(ch=='-')f*=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+(ch-'0');ch=getchar();}
	return x * f;
}
int nedge=0,p[400001],nex[400001],head[400001],n,m;
bool b[200001];
int sum=0;
inline void addedge(int a,int b){
    p[++nedge]=b;nex[nedge]=head[a];head[a]=nedge;
}
void dfs(int x)
{
	for(int k = head[x]; k; k = nex[k])
	{
		++sum;
		if(!b[p[k]])	b[p[k]]=true,dfs(p[k]);
	}
} 
int main()
{
	n = read() , m = read();
	for(int i = 1 ; i <= n ; i++)
	{
		int x = read() , y = read();
		addedge(x,y),addedge(y,x);	//把第i个球能投进的两个框连起来 
	}
	int ans = 0;
	for(int i = 1 ; i <= m ; i++)
		if(!b[i])
		{
			b[i]=true;	sum=0; dfs(i);
			sum>>=1;
			if(sum&1) ans++;
		}
	printf("%d",ans); 	
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值