一道奇葩的ACM题所带给我的人生哲理

http://poj.org/problem?id=1466

在此贴上原题地址,POJ一道转自2000年欧盟题的老古董了。

题目原文是英文的,作为一个英语苦手我大致明白了它的意思:

”给定一群学生,其中某些男女学生之间可以在一起,计算一种配对方案,使单身狗个数最多。“(这题一定是教导主任出的吧!)

乍一看这似乎是一道并查集,通过”男“”女“的界定要想到冷门一些的二分图也不是很难。

到目前为止,这就是一道求最大独立树的纯水题。But

 ┄┅┄┅┄┅┄┅┄* 

看看测试数据吧

7
0: (3) 4 5 6
1: (2) 4 6
2: (0)
3: (0)
4: (2) 0 1
5: (1) 0
6: (2) 0 1
题目既然是 Girls and Boys(不得不想起一个叫做Boys Like Girls的娘炮乐队),那么是大约可以否认基佬和百合的存在了♂,也就是说在正常人的思维内,一个保证不出现环的图已经成型了,手打匈牙利算法准备自信秒杀。

Source Code
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int p,n,date[700][700],state[700],result[700];
bool find(int a)
{
	int i;
	for(i=0;i<p;i++)
	{
		if(date[a][i]==1&&!state[i])
		{
			state[i]=true;
			if(result[i]==0||find(result[i]))
			{
				result[i]=a;
				result[a]=i;
				return true;
			}
		}
	}
	return false;
}
int diablos=1;
int main()
{
	while(scanf("%d",&p)!=EOF)
	{
	int i,j,k,o,ans=0;
    memset(result,0,sizeof(result));
    memset(date,0,sizeof(date));
	for(i=0;i<p;i++)
	{
		scanf("%d: (%d)",&n,&k);
		for(j=1;j<=k;j++)
		   {
		   	scanf("%d",&o);
		   	date[i][o]=1;
                        date[o][i]=1
		   }
        }
	for(i=1;i<=p;i++)
	   {
	   	memset(state,0,sizeof(state));
	   	if(find(i))
	   	  ans++;
	   }
       printf("%d\n",p-ans);
   }
}

自信满满提交 and 如图

改了一个晚上始终都是WA,暴怒的我终于无法容忍过不了这样一道水题,果断出绝招

”XXX快点过来帮我看一下一道题!“

”我这会没空,我把我的程序发给你看一下嘛“

于是楼主认真地研究了大神的代码,一段时间之后

我第六次肯定除了变量名之外我绝对没有和大神不一样的地方!

实在无可奈何决定去请教老师,可是遗憾的是老师也没有标程,陪我一起盯着那道题看。

这时正在听歌的某大神忽然一声高呼:

”你快点回来,我把我写错的那个程序发给你了!“

顿时我吐血三升倒地而亡........

在大神的指导下我修改了两个细节成功AC害羞

Source Code
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int p,n,date[700][700],state[700],result[700],mark;
bool find(int a)
{
	int i;
	state[a]=true;
	for(i=0;i<p;i++)
	{
		if(date[a][i]==1&&!state[i])
		{
			state[i]=true;
			if(result[i]==-1||find(result[i]))
			{
				result[i]=a;
				return true;
			}
		}
	}
	return false;
}
int main()
{
	while(scanf("%d",&p)!=EOF)
	{
	int i,j,k,o,ans=0;
    memset(result,-1,sizeof(result));
    memset(date,0,sizeof(date));
	for(i=0;i<p;i++)
	{
		scanf("%d: (%d)",&n,&k);
		for(j=0;j<k;j++)
		   {
		   	scanf("%d",&o);
		   	date[i][o]=1;
		   }
	}
	for(i=0;i<p;i++)
	   {
	   	memset(state,false,sizeof(state));
	   	if(find(i))
	   	  ans++;
	   }
       printf("%d\n",p-ans/2);
   }
}

细心的宝宝有没有发现呢(づ。◕‿‿◕。)づ

这道题所构建的的边应该都是单向边!!!所以在find时的匹配操作就应该只改变一个点的指向值。

 可是机智如我为什么会产生这是一个无向图的误会呢?

倒回去看题目自带样例!!!

所有前面出现过的”好感“(姑且可以这么讲嘛)都在后面有过回应。

所以天真如我就毫不犹豫的认为只要喜欢一个人就是可以在一起的~(大雾~)

但是样例如此,事实并非如此!

很可能你朝思暮想的人根本鸟都不想鸟你!

童话里都是骗人的233333......

可是单向变的话,为啥某点单向匹配了一个点之后,会导致某点自己无法再去匹配别人呢?

机智如我立刻想通了关窍!

“你的心已经交给TA了怎么可能还交给别人啊!”

所以最后的结果是,屌丝单相思着他的女神,可是也没可能和女神在一起,也不会想去和别的女生在一起,

于是教导主任罪恶的目的就这样愉快地达到了!♂♂♂

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一道ACM题目的示例: 题目描述 给定一个整数数组和一个目标值,找出数组中和为目标值的两个数。 你可以假设每个输入只对应一种答案,且同样的元素不能重复使用。 示例 给定 nums = [2, 7, 11, 15], target = 9 因为 nums[0] + nums[1] = 2 + 7 = 9 所以返回 [0, 1] 解思路 这道可以使用哈希表来解决。哈希表中存储每个数的下标,遍历数组时,判断哈希表中是否存在 target-nums[i],如果存在,则说明找到了符合要求的两个数,返回它们的下标即可。 代码实现 C++代码实现: ```cpp #include <iostream> #include <vector> #include <unordered_map> using namespace std; vector<int> twoSum(vector<int>& nums, int target) { unordered_map<int, int> m; for (int i = 0; i < nums.size(); i++) { int complement = target - nums[i]; if (m.count(complement)) { return {m[complement], i}; } m[nums[i]] = i; } return {}; } int main() { vector<int> nums = {2, 7, 11, 15}; int target = 9; vector<int> res = twoSum(nums, target); for (int i = 0; i < res.size(); i++) { cout << res[i] << " "; } return 0; } ``` Python代码实现: ```python def twoSum(nums, target): d = {} for i, n in enumerate(nums): complement = target - n if complement in d: return [d[complement], i] d[n] = i return [] nums = [2, 7, 11, 15] target = 9 print(twoSum(nums, target)) ``` Java代码实现: ```java import java.util.HashMap; public class Solution { public int[] twoSum(int[] nums, int target) { HashMap<Integer, Integer> map = new HashMap<>(); for (int i = 0; i < nums.length; i++) { int complement = target - nums[i]; if (map.containsKey(complement)) { return new int[] {map.get(complement), i}; } map.put(nums[i], i); } return new int[] {}; } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值