UVa 10763 Foreign Exchange

本文介绍了解决UVa10763 Foreign Exchange问题的三种方法,包括一种利用计数数组实现的O(n)算法,一种通过交换元素验证可行性的巧妙思路,以及一种基于集合查找配对的nlogn算法,并提供了第三种方法的具体实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

UVa 10763 Foreign Exchange

题解

本来在疑惑nlogn是不是正解,搜了搜这道题方法好像很多。
方法一:设K=max(A,B),K*K不MLE的话,可以O(n)做,即用cnt[i][j]记录从i换到j有多少个人。
方法二:这是我看到的一个方法,感觉很巧妙,使用swap,因为如果可行的话,存在a->b必定存在b->a,那么如果先构造一个序列放在c中 1 2 3 4 5 …每次读入一对a,b就swap(c[a],c[b]),如果最后序列还是1 2 3 4 5 ..就可行。很巧妙,但是我想说这种解法有问题比如两个需求1 2和1 2就挂掉了,如果能A只能说明数据太太太水辣!
方法三:自己想的nlogn,最易行的办法,直接扔一个结构体到set里面然后每次去找一找存不存在配对的就行了,不存在就扔进去,存在就计数并把配对的那个删掉。怀疑结构体会有点慢所以我定义 ci=(ai<<31)+bi ,这样用一个longlong就可以了,(有点像无冲突哈希?),时间感觉也不是很慢,130ms,突然想到也许用hashtable会快一些貌似能做到O(n)(雾)。

代码

方法三代码

//QWsin
#include<set>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=500000+10;

multiset<ll>dict;

int n,a[maxn],b[maxn];

inline ll cal(int a,int b){return ((1ll*a)<<31)+b;}
inline void solve()
{
    for(int i=1;i<=n;++i) scanf("%d%d",a+i,b+i);

    int cnt=0;
    for(int i=1;i<=n;++i)
    {
        ll c=cal(b[i],a[i]);
        if(dict.count(c)) cnt+=2,dict.erase(dict.find(c));
        else dict.insert(cal(a[i],b[i]));
    }
    puts(cnt==n?"YES":"NO");
}

int main()
{
    while(scanf("%d",&n)==1&&n) solve();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值