C - 位置信息挖掘 FZU - 2192-并查集

题目:


O2O即Online To Offline,是指将线下的商务机会与互联网结合,让互联网成为线下交易的前台。这些商务机会主要是偏服务类的商品,例如汽车售后服务、摄影服务、餐饮、电影等,其特色是线上购买、线下服务。

因此,对这类垂直行业的商品做移动推荐时,用户和商品的位置信息显得格外重要。但是,可能存在用户、商品的位置信息缺失的情况,例如:用户不共享位置信息、商家未填写位置信息……

现在,Jason给出用户在移动端的购买行为数据,以及商品集合,希望能补全一些缺失的位置信息。为了简化问题,假设:

1、由于是服务类的商品,如果用户位于城市A,那么该用户只会购买位于城市A的商品。

2、数据不存在噪声,即测试数据都是合法的。

Input

包含多组数据

每组输入数据格式如下:

第一行,三个数:N、M、Q,表示N个商品,M条购买行为数据,Q个询问。

接下来N行,每行两个数:itemId、cityId,表示商家填写的服务itemId,位于城市cityId。

接下来M行,每行三个数:userId、itemId、cityId,表示用户userId购买了服务itemId,移动端定位城市cityId。

接下来Q行,每行两个数:0、itemId或者1、userId,表示询问服务itemId所在的城市,或者用户userId所在的城市。

注意:0表示位置信息缺失。

Output
每组输出数据格式如下: Q行,每行一个数:cityId,表示服务itemId位于cityId,或者用户userId位于cityId。
Sample Input
3 2 5
2 0
3 0
1 3
2 2 2
1 1 0
0 1
0 2
0 3
1 1
1 2
Sample Output
3
2
0
3
2
Hint

1<=N<=LIMIT

1<=M<=LIMIT

1<=Q<= N+M

1<=itemId<=N

1<=userId<=M

0<=cityId<=N+M,0表示位置信息缺失

对于60%的数据,LIMIT<=10^2;对于100%的数据,LIMIT<=10^5


         思路:多对一的并查集+hash,具体思路见代码。

         代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
using namespace std;
typedef long long ll;
const double PI = acos(-1.0);
const double eps = 1e-6;
const int INF = 1000000000;
const int maxn = 444444;
int T,n,m,q;
int a,b,c;
int f[maxn];

void init()
{
    for(int i=0;i<maxn;i++)
        f[i]=i;
}

int Get_f(int v)
{
    if(f[v]==v)
        return v;
    else
        return f[v]=Get_f(f[v]);
}

void Merge(int u,int v)
{
    int uu=Get_f(u);
    int vv=Get_f(v);
    //这里要swap的原因是因为要保证使得f[小的]=大的,因为当用户与服务合并时如果一方没有对应的城市那么
    //没有对应的城市的那一方的f值等于自己的编号必定小与有城市一方的f值
    //于是更新f值小的一方
    if(vv<uu)
        swap(vv,uu);
    if(uu!=vv)
        f[uu]=vv;
}

int main()
{
    while(scanf("%d%d%d",&n,&m,&q)!=EOF)
    {
        init();
        //由于这里并查集f[i]=j表示用户i或者服务i对应的城市为j,但是本题用户服务和城市编号都会重复,于是
        //要hash映射一下
        //城市编号加上n+m保证比用户和服务的编号都大
        //用户编号加上n,服务编号不变
        for(int i=0;i<n;i++)
        {
            scanf("%d%d",&a,&b);
            if(b!=0)
                Merge(a,b+n+m);
        }
        for(int j=0;j<m;j++)
        {
            scanf("%d%d%d",&a,&b,&c);
            Merge(a+n,b);
            if(c!=0)
                Merge(b,c+n+m);
        }
        for(int i=0;i<q;i++)
        {
            scanf("%d%d",&a,&b);
            if(a==1)
                b+=n;
            if(Get_f(b)>=n+m)
                printf("%d\n",Get_f(b)-n-m);
            else
                printf("%d\n",0);
        }
    }
    return 0;
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值