传送门

题意:

  给出集合U,V,集合U有n个元素,集合V有m个元素;

  有 m 个操作,mi : s1 s2 有一条s1指向s2的边(s1,s2可能属于第三个集合,暂且称之为K集合);

  指向边具有传递性,即 A->B,B->C <=> A->C

  求V集合中被 U 指向的元素;

题解:

  并查集debug个了两天,始终wa,今天上午上数字逻辑课的时候,灵光一闪,又想到了一个可能会出错的点;

  经过一番挣扎,终于判断了此题不能用并查集做,蓝瘦香菇~~~~~~

  还记得并查集中的Union(x,y)操作吗?

  此函数得作用是将 x元素 所在的集合与 y元素 所在得集合合并成一个大集合;

  对于此题,初始想法是,并查集中只保存

    ①U 集合指出去的边

    ②K 集合指向 V 集合的边

    ③V 集合指向 V 集合的边

  如果满足上述三种条件,则Union(s1,s2);

  最后,判断V集合中元素的Find(s)是否属于U集合,如果属于,则输出s;

  那么,问题来了,s1,s2真的可以这么合并吗?

  看如下连接方式:

  

  输入的顺序是:

    v2 v1

    k2 v1

  对于第一条指令,Union(v2,v1)是没得说的,此时 fa(v1) = v2 , fa(v2) =v2

  对于第二条指令,可以调用 Union(k2,v1) 吗?

  先看看调用后的结果:Find(k2) = k2 , Find(v1) = v2 , k2 ≠ v2 , fa(v1)=fa(v2)=k2; ???

  那么,再加入一条边呢?

    u1 k2

  

  那么,此时调用Union(u1,k2) : fa(k2) = u1;

  当输出时:

    v1 : Find(v1) = Find(k2) = u1 ,输出 v1

    v2 : Find(v2) = Find(k2) = u1 ,输出 v2

  这就出现问题了吧!!!

  那,如果人为的将 fa(v1) = k2,但是fa(v2) = v2呢?

  看一下接下来的这张图:

  加入边 u2 v2

  

  

  输出时:

    v1 : Find(v1) = k2 ,不输出 v1

    v2 : Find(v2) = u2 ,输出 v2

  又出现错误了,是吧!

  为什么并查集会出现这个问题呢?

  v1,v2属于同一个集合,v1,k2属于同一个集合,但 k2,v2并不能属于同一个集合,所以不能合并;

  看来,当图是有向图时,慎用并查集!!!!!!!!!!!!!

  

  所以说,还是搜索大法好!!!!

AC代码:

 #include<iostream>
#include<cstdio>
#include<map>
#include<cstring>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
const int maxn=1e4+; int n,m,x;
int numU,numV;//[1,numU]集合U的编号范围,[numU+1,numV]:集合V的编号范围
bool vis[maxn];//vis[i]:判断属于V集合的编号i是否有条被U集合指向的边
bool rep[maxn];//rep[i]:判断i编号对应的字符串是否重复出现在U,V集合中
int head[maxn];
int num;
struct Edge
{
int to;
int next;
}G[*maxn];
void addEdge(int u,int v)
{
G[num].to=v;
G[num].next=head[u];
head[u]=num++;
}
map<string ,int >mymap;//将字符串映射成整数 bool isSetU(int xx)//判断节点xx是否属于U集合
{
return xx >= && xx <= numU;
}
bool isSetV(int xx)//判断节点xx是否属于V集合
{
return xx > numU && xx <= numV;
}
void DFS(int u)
{
vis[u]=true;//被集合U指向的节点
for(int i=head[u];~i;i=G[i].next)
{
int v=G[i].to;
if(!vis[v])
DFS(v);
}
}
void Solve(int id)
{
for(int i=;i <= x;++i)
{
string s1,s2;
cin>>s1>>s2;
if(!mymap.count(s1))
mymap[s1]=++id;
if(!mymap.count(s2))
mymap[s2]=++id;
int u=mymap[s1];
int v=mymap[s2];
addEdge(u,v);
}
map<string ,int>::iterator it;
for(it=mymap.begin();it != mymap.end();++it)
{
int x=it->second;
if(!isSetU(x) || vis[x])
continue;
//以集合U中的元素为起点开始搜索
DFS(x);
}
bool flag=false;
for(it=mymap.begin();it != mymap.end();++it)
{
int x=it->second;
if(rep[x] || isSetV(x)&&vis[x])
{
if(!flag)
cout<<it->first;
else
cout<<" "<<it->first;
flag=true;
}
}
cout<<"\n";
}
void Init()
{
num=;
mem(head,-);
mem(rep,false);
mem(vis,false);
mymap.clear();
}
int main()
{
// freopen("C:\\Users\\hyacinthLJP\\Desktop\\in&&out\\contest","r",stdin);
ios::sync_with_stdio(false);
cin.tie();
cout.tie(); int test;
cin>>test;
while(test--)
{
Init();
cin>>n>>m>>x;
int id=;
for(int i=;i <= n;++i)
{
string s;
cin>>s;
mymap[s]=++id;
}
numU=id;
for(int i=;i <= m;++i)
{
string s;
cin>>s;
if(!mymap.count(s))
mymap[s]=++id;
else
rep[mymap[s]]=true;//重复出现的字符串
}
numV=id;
Solve(id);
}
return ;
}

Stanford Local 2016 E "Election of Evil"(搜索(正解)或并查集(划掉))的更多相关文章

  1. Stanford Local 2016 G "Ground Defense"(线段树)

    传送门 题意: 有 n 个城市,编号 1~n: 有两种操作:Update,Query Update: E i s a d 更新区间[ i,i+d-1 ], i 节点降落 s 人, i+1 节点降落 s ...

  2. 2018.09.24 bzoj1016: [JSOI2008]最小生成树计数(并查集+搜索)

    传送门 正解是并查集+矩阵树定理. 但由于数据范围小搜索也可以过. 我们需要知道最小生成树的两个性质: 不同的最小生成树中,每种权值的边出现的个数是确定的 不同的生成树中,某一种权值的边连接完成后,形 ...

  3. upc组队赛5 Election of Evil【搜索】

    Election of Evil 题目描述 Dylan is a corrupt politician trying to steal an election. He has already used ...

  4. HDU 5923 Prediction(2016 CCPC东北地区大学生程序设计竞赛 Problem B,并查集)

    题目链接  2016 CCPC东北地区大学生程序设计竞赛 B题 题意  给定一个无向图和一棵树,树上的每个结点对应无向图中的一条边,现在给出$q$个询问, 每次选定树中的一个点集,然后真正被选上的是这 ...

  5. 【搜索】【并查集】Codeforces 691D Swaps in Permutation

    题目链接: http://codeforces.com/problemset/problem/691/D 题目大意: 给一个1到N的排列,M个操作(1<=N,M<=106),每个操作可以交 ...

  6. Codeforces Gym 101194G Pandaria (2016 ACM-ICPC EC-Final G题, 并查集 + 线段树合并)

    题目链接  2016 ACM-ICPC EC-Final Problem G 题意  给定一个无向图.每个点有一种颜色. 现在给定$q$个询问,每次询问$x$和$w$,求所有能通过边权值不超过$w$的 ...

  7. HDU3926Hand in Hand(搜索 或 并查集)

    Problem Description In order to get rid of Conan, Kaitou KID disguises himself as a teacher in the k ...

  8. Elastic Stack 笔记(六)Elasticsearch5.6 搜索详解

    博客地址:http://www.moonxy.com 一.前言 Elasticsearch 主要包含索引过程和搜索过程. 索引过程:一条文档被索引到 Elasticsearch 之后,默认情况下 ES ...

  9. NOIp2016 D2T3 愤怒的小鸟【搜索】(网上题解正解是状压)

    题目传送门 没啥别的想法,感觉就是搜索,经过原点的抛物线已知两个点就可以求出解析式,在还没有被打下来的两个猪之间随意配对,确定解析式之后标记在这个抛物线下被打下来的猪. 猪也可以单独用一个抛物线打下来 ...

随机推荐

  1. Linux 环境 Java JDK 安装&基本配置

    索引: 目录索引 参看代码 GitHub: jdk.txt 一.Linux (DeepinOS) 环境 1.官网下载 jdk-8u112-linux-x64.tar.gz 2.创建目录 mkdir - ...

  2. T-SQL_select语句详解

    select语句执行的过程: 先看查询内容 ==>where条件 ==>[分组条件] ==>[分组搜索条件] ==>内容输出 ==>[是否排序] SQL中SELECT语句 ...

  3. 一些常用的meta标签

    <!DOCTYPE html> <!-- 使用 HTML5 doctype,不区分大小写 --> <html lang="zh-cmn-Hans"&g ...

  4. iOS transform属性的使用

    1.transform属性 在iOS开发中,通过transform属性可以修改UIView对象的平移.缩放比例和旋转角度,常用的创建transform结构体方法分两大类 (1) 创建“基于控件初始位置 ...

  5. Task.Wait and “Inlining”

    “What does Task.Wait do?” Simple question, right? At a high-level, yes, the method achieves what its ...

  6. Python 函数初识 (1)

    一.今日主要内容 认识函数 函数:对功能或者动作的封装(定义) 语法: def 函数名字(形参) 函数体 函数的调用格式:函数名(实参) 函数的返回值 关键字:return 终止函数的运行 1.函数内 ...

  7. KafkaManager编译安装使用(支持kerberos认证)

    为了能够方便的查看及管理Kafka集群,yahoo提供了一个基于Web的管理工具(Kafka-Manager). 这个工具可以方便的查看集群中Kafka的Topic的状态(分区.副本及消息量等),支持 ...

  8. python接口自动化-get请求

    一.环境安装 1.用pip安装requests模块 >>pip install requests 二.get请求 1.  url 1.1:   response 的返回内容还有很多信息,例 ...

  9. 第十届蓝桥杯省赛JavaB组个人题解

    前言 以下的第十届蓝桥杯Java B组省赛的题目题解只是我个人的题解,提供一些解题思路,仅作参考,如有错误,望大家指出,不甚感激,我会及时更改. 试题 A: 组队 ----- 答案:490 [问题描述 ...

  10. TortoiseGit 安装

    1.TortoiseGit 下载安装 2.语言包下载安装 3.配置语言 一 TortoiseGit 下载安装 官网下载地址:https://download.tortoisegit.org/tgit/ ...