2017省夏令营Day8 【bfs,并查集】

题解:出题人丧心病狂~ 对于这道题,我们对每一个内应节点bfs,并用并查集维护,如果s和t联通,输出答案并break。

PS几个小细节:①对于每个内应dis=0,为了保证不会对答案产生影响,我们在每2个节点中插入一个新的节点即可;

②因为加入新节点,数组要开大些,否则会炸。

代码如下:

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #define Max 2020304
 5 using namespace std;
 6 int n,m,k,s,t,dis[Max],fa[Max],hd,tl,q[Max*2];
 7 int tot,to[Max],next[Max],head[Max];
 8 bool flag,vis[Max];
 9 void add(int x,int y){
10     to[++tot]=y; next[tot]=head[x]; head[x]=tot;
11     to[++tot]=x; next[tot]=head[y]; head[y]=tot;
12 }
13 int find(int x){
14     if(fa[x]==0) return x;
15     return fa[x]=find(fa[x]);
16 }
17 void prework(){
18     flag=true; hd=0; tl=k;
19     memset(fa,0,sizeof(fa));
20     memset(vis,0,sizeof(vis));
21     memset(dis,-1,sizeof(-1));
22     for(int i=1;i<=k;i++) vis[q[i]]=true,dis[q[i]]=0;
23 }
24 void bfs(){
25     prework();
26     while(hd<tl){
27         int vex=q[++hd]; if(!flag) break;
28         for(int i=head[vex];i;i=next[i]){
29             if(!flag) break;
30             int u=find(vex),v=find(to[i]);
31             if(u!=v) fa[u]=v;
32             if(find(s)==find(t)){printf("%d\n",dis[vex]+1); flag=false; break;}
33             if(!vis[to[i]]){
34                 dis[to[i]]=dis[vex]+1;
35                 vis[q[++tl]=to[i]]=true;
36             }
37         }
38     }
39     if(flag) printf("-1\n");
40 }
41 int main()
42 {
43     freopen("masquerade.in","r",stdin);
44     freopen("masquerade.out","w",stdout);
45     int T; scanf("%d",&T);
46     while(T--){
47         memset(head,tot=0,sizeof(head));
48         memset(to,0,sizeof(to));
49         memset(next,0,sizeof(next));
50         scanf("%d%d%d",&n,&m,&k);
51         for(int i=1;i<=k;i++) scanf("%d",&q[i]);
52         int now=n;
53         for(int i=1;i<=m;i++){
54             int x,y; scanf("%d%d",&x,&y);
55             add(x,++now); add(now,y);
56         }
57         scanf("%d%d",&s,&t); q[++k]=t;
58         bfs();
59     }
60 }

---------------------------------------------------------------华丽的分割线------------------------------------------------------------------------

---------------------------------------------------------------华丽的分割线------------------------------------------------------------------------

时间: 2024-11-05 06:25:20

2017省夏令营Day8 【bfs,并查集】的相关文章

ZOJ 3811 Untrusted Patrol bfs+并查集

题目链接:点击打开链接 题意: 给定n个点m条边的无向图,k个触发器. 下面k个数表示触发器安装在哪几个点. 下面m行给出边 最后有l个信号, 给出信号发出的触发器的顺序. 每个触发器只会发出一次信号,且一个点只有一个触发器. 有一个人在遍历图. 每经过一个点,那个点的触发器就会发出信号,问是否存在一种走法使得这个人遍历了所有点且触发器发出的信号顺序和给出的一样. 思路: 先把无触发器的点放到图里. 然后根据触发器的信号顺序把点依次加入图中,加入时只添加(与无触发器点相连的边) 然后判断这个点能

百度之星2017 HDU 6109 数据分割 并查集+set

数据分割 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6109 Description 小w来到百度之星的赛场上,准备开始实现一个程序自动分析系统.这个程序接受一些形如xi=xj 或 xi≠xj 的相等/不等约束条件作为输入,判定是否可以通过给每个 w 赋适当的值,来满足这些条件.输入包含多组数据.然而粗心的小w不幸地把每组数据之间的分隔符删掉了.他只知道每组数据都是不可满足的,且若把每组数据的最后一个约束条件去掉,则该组数据是可满足的.请帮助他

zoj3811Untrusted Patrol((bfs+并查集)

题目链接: huangjing 题意: 一个工厂有n个点,有k个点是由传感器的,然后最后给l个传感器先后出现的位置,一个传感器只能记录一次..最后判断保安是否所有的点都可能走到了?? 思路: 详见下面的代码中的解释 题目: Untrusted Patrol Time Limit: 3 Seconds      Memory Limit: 65536 KB Edward is a rich man. He owns a large factory for health drink producti

Java版的广度优先寻路(BFS+并查集思想)

import java.util.Deque; import java.util.LinkedList; class node{ int x; int y; } class Solution{ private int dir[][]=new int[][] {{0,-1},{-1,0},{0,1},{1,0}}; private node parentx[][]; private int Count[][]; private boolean used[][]; private node star

ZOJ 3811 / 2014 牡丹江赛区网络赛 C. Untrusted Patrol bfs/dfs/并查集

Untrusted Patrol Time Limit: 3 Seconds                                     Memory Limit: 65536 KB Edward is a rich man. He owns a large factory for health drink production. As a matter of course, there is a large warehouse in the factory. To ensure t

第三次周赛题解【并查集 KMP DFS BFS 快速幂】

问题 A: 一道签到题 时间限制: 2 Sec  内存限制: 128 MB 提交: 63  解决: 28 [提交][状态][讨论版] 题目描述 我想说这是一道签到题,意思就是本次测试中最水的一道,不过我这样说你真的愿意相信我吗?哈哈,题目是这样的给你一下小数,然后请告诉我分别告诉我这个小数的循环节的循环次数.循环节以及循环节长度 输入 输入包括多组测试数据每组测试数据1行,包括一个小数,小数的长度不超过200,小数大于0小于100 输出 分别输出这个小数的循环节的长度.循环节以及循环次数,中间以

HDU 2017 Code Lock (并查集的应用+快速幂)

链接:HDU 3461 题目大意: 题目的大意是一个密码锁上有编号为1到N的N个字母,每个字母可以取26个小写英文字母中的一个.再给你M个区间[L,M],表示该区间的字母可以一起同步"增加"(从'a'变为'b'为增1,'z'增1为'a').假如一组密码按照给定的区间进行有限次的"增加"操作后可以变成另一组密码,那么我们认为这两组密码是相同的.该题的目标就是在给定N.M和M个区间的前提下计算有多少种不同的密码. 根据题意,如果一个可调整的区间都没有的话,答案应该是26

2017端午欢乐赛——Day1T3(树的直径+并查集)

//前些天的和jdfz的神犇们联考的模拟赛.那天上午大概是没睡醒吧,考场上忘了写输出-1的情况,白丢了25分真是**. 题目描述     小C所在的城市有 n 个供电站,m条电线.相连的供电站会形成一个供电群,那么为了节省材料,供电群是一棵树的形式,也即城市是一个森林的形式(树:V个点,V-1条边的无向连通图,森林:若干棵树).每个供电群中不需要所有供电站都工作,最少只需要一个工作,其余的就都会通过电线收到电,从而完成自己的供电任务.当然,这样会产生延迟.定义两个供电站的延迟为它们之间的电线数量

畅通工程(自己写的BFS,但后面想了下并查集更好更快)

某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇.省政府"畅通工程"的目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要互相间接通过道路可达即可).问最少还需要建设多少条道路? Input测试输入包含若干测试用例.每个测试用例的第1行给出两个正整数,分别是城镇数目N ( < 1000 )和道路数目M:随后的M行对应M条道路,每行给出一对正整数,分别是该条道路直接连通的两个城镇的编号.为简单起见,城镇从1到N编号. 注意:两个城市