BZOJ5203 [NEERC2017 Northern] Grand Test 【dfs树】【构造】

题目分析:

  首先观察可知这是一个无向图,那么我们构建出它的dfs树。由于无向图的性质我们可以知道它的dfs树只有返祖边。考虑下面这样一个结论。

  结论:若一个点的子树中(包含自己)有两个点有到它祖先的返祖边(不包括到它自己),

  首先我们证明S和T肯定在DFS树中是祖先关系,接着证明到T至少有一条返祖边,那么这个结论就是显然的了。

代码:

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3
  4 const int maxn = 102000;
  5
  6 int n,m;
  7 vector <int>g[maxn];
  8
  9 int up[maxn],dep[maxn],wh[maxn],fa[maxn];
 10 int flag, from, to;
 11
 12 void read(){
 13     scanf("%d%d",&n,&m);
 14     for(int i=1;i<=n;i++) g[i].clear();
 15     for(int i=1;i<=m;i++){
 16     int u,v; scanf("%d%d",&u,&v);
 17     g[u].push_back(v); g[v].push_back(u);
 18     }
 19 }
 20
 21 int r1[maxn],num1;
 22 int r2[maxn],num2;
 23 int r3[maxn],num3;
 24 int md;
 25 stack <int> s;
 26 void print(int now){
 27     int pla = now;
 28     while(dep[pla] != to) r1[++num1] = pla,pla = fa[pla];
 29     r1[++num1] = pla;
 30
 31     pla = md;
 32     while(dep[pla] != dep[now]) s.push(pla),pla = fa[pla];
 33     s.push(pla);
 34     while(!s.empty()){r2[++num2] = s.top();s.pop();}
 35     r2[++num2] = r1[num1];
 36
 37     pla = wh[now];
 38     while(dep[pla] != dep[now]) s.push(pla),pla = fa[pla];
 39     s.push(pla);
 40     while(!s.empty()){r3[++num3] = s.top();s.pop();}
 41     pla = r1[num1];
 42     while(dep[pla] != up[now]) s.push(pla),pla = fa[pla];
 43     s.push(pla);
 44     while(!s.empty()){r3[++num3] = s.top();s.pop();}
 45
 46     printf("%d %d\n",r1[1],r1[num1]);
 47     printf("%d ",num1);for(int i=1;i<=num1;i++) printf("%d ",r1[i]);
 48     puts("");
 49     printf("%d ",num2);for(int i=1;i<=num2;i++) printf("%d ",r2[i]);
 50     puts("");
 51     printf("%d ",num3);for(int i=1;i<=num3;i++) printf("%d ",r3[i]);
 52     puts("");flag = 1;
 53 }
 54
 55 void dfs(int now,int dp){
 56     dep[now] = dp;
 57     for(int i=0;i<g[now].size();i++){
 58     int nxt = g[now][i];
 59     if(fa[now] == nxt) continue;
 60     if(flag) break;
 61     if(dep[nxt] == 0){
 62         fa[nxt] = now;
 63         dfs(nxt,dp+1); if(flag) break;
 64         if(up[nxt] >=  dep[now]) continue;
 65         if(up[now] >= 10000000) up[now] = up[nxt],wh[now] = wh[nxt];
 66         else{
 67         if(up[now] <= up[nxt]){
 68             from = now; to = up[nxt];md = wh[nxt];
 69         }else {
 70             from = now; to = up[now];up[now] = up[nxt];
 71             md = wh[now];wh[now]= wh[nxt];
 72         }
 73         print(from);
 74         }
 75     }else{
 76         if(dep[nxt] > dep[now]) continue;
 77         if(up[now] >= 10000000) up[now] = dep[nxt],wh[now] = now;
 78         else{
 79         if(up[now] <= dep[nxt]){
 80             from = now; to = dep[nxt];md = now;
 81         }else {
 82             from = now; to = up[now];up[now] = dep[nxt];
 83             md = wh[now];wh[now] = now;
 84         }
 85         print(from);
 86         }
 87     }
 88     }
 89 }
 90
 91 void work(){
 92     flag = 0; from = 0; to = 0; num1 = num2 = num3 = 0;
 93     for(int i=0;i<=n;i++) wh[i] = 0,fa[i] = 0,dep[i] = 0,up[i] = 1e9;
 94     for(int i=1;i<=n;i++) if(!dep[i]) dfs(i,1);
 95     if(!flag){puts("-1");}
 96 }
 97
 98 int main(){
 99     int cas; scanf("%d",&cas);
100     while(cas--){
101     read();
102     work();
103     }
104     return 0;
105 }

原文地址:https://www.cnblogs.com/Menhera/p/8900620.html

时间: 2024-08-30 06:03:10

BZOJ5203 [NEERC2017 Northern] Grand Test 【dfs树】【构造】的相关文章

Codeforces 453C Little Pony and Summer Sun Celebration dfs树上构造

题目链接:点击打开链接 题意: 给定一个无向图 任选一个起点,使得访问每个点的次数奇偶与最后一行的输入一致 思路: 选一个奇数点作为起点 dfs树一下,若子节点不满足则先走到子节点再回来 如此就能保证所有子节点合法 这样dfs结束后最多只有根节点不满足,随便找一个与根相连的点调整一下. #include <stdio.h> #include <string.h> #include <iostream> #include <math.h> #include &

Codeforces Round #423 (Div. 2) C 思维,并查集 或 线段树 D 树构造,水

Codeforces Round #423 (Div. 2, rated, based on VK Cup Finals) C. String Reconstruction   思维,并查集 或 线段树 题意:一个字符串被删除了,但给出 n条信息,要还原出可能的字典序最小的字符串.信息有:字符串ti,ki个位置xi,表明原本的字符串在xi位置是以字符串ti开头的. tags:惨遭 fst,一开始把所有字符串都存下来,排序做的,结果爆内存了.. 方法1: 考虑并查集,对于字符串 ti,在位置xi,

BZOJ 4541: [Hnoi2016]矿区 平面图转对偶图+DFS树

4541: [Hnoi2016]矿区 Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 433  Solved: 182[Submit][Status][Discuss] Description 平面上的矿区划分成了若干个开发区域.简单地说,你可以将矿区看成一张连通的平面图,平面图划分为了若 干平面块,每个平面块即为一个开发区域,平面块之间的边界必定由若干整点(坐标值为整数的点)和连接这些整点 的线段组成.每个开发区域的矿量与该开发区域的面积有关:具

【BZOJ4238】电压 DFS树

[BZOJ4238]电压 Description 你知道Just Odd Inventions社吗?这个公司的业务是“只不过是奇妙的发明(Just Odd Inventions)”.这里简称为JOI社. JOI社的某个实验室中有着复杂的电路.电路由n个节点和m根细长的电阻组成.节点被标号为1~N 每个节点有一个可设定的状态[高电压]或者[低电压].每个电阻连接两个节点,只有一端是高电压,另一端是低电压的电阻才会有电流流过.两端都是高电压或者低电压的电阻不会有电流流过. 某天,JOI社为了维护电路

【bzoj4016】[FJOI2014]最短路径树问题 堆优化Dijkstra+DFS树+树的点分治

题目描述 给一个包含n个点,m条边的无向连通图.从顶点1出发,往其余所有点分别走一次并返回. 往某一个点走时,选择总长度最短的路径走.若有多条长度最短的路径,则选择经过的顶点序列字典序最小的那条路径(如路径A为1,32,11,路径B为1,3,2,11,路径B字典序较小.注意是序列的字典序的最小,而非路径中节点编号相连的字符串字典序最小).到达该点后按原路返回,然后往其他点走,直到所有点都走过. 可以知道,经过的边会构成一棵最短路径树.请问,在这棵最短路径树上,最长的包含K个点的简单路径长度为多长

根据中序遍历和后序遍历树构造二叉树

样例: 给出树的中序遍历: [1,2,3] 和后序遍历: [1,3,2] 返回如下的树: 2 /  \ 1   3 借鉴上一篇<前序遍历和中序遍历树构造二叉树>,我们知道中序遍历为左->中->右,后序遍历为左->右->中.于是后序遍历的最后一个值即为根节点的值,根据这个值我们在中序遍历中找到根节点左子树和右子树的值,递归构造左子树和右子树即可. /** * Definition of TreeNode: * class TreeNode { * public: * in

LintCode(72)中序遍历和后序遍历树构造二叉树

题目 中序遍历和后序遍历树构造二叉树 根据中序遍历和后序遍历树构造二叉树 样例 给出树的中序遍历: [1,2,3] 和后序遍历: [1,3,2] 返回如下的树: 2 /  \ 1    3 分析 递归解决. Python代码 """ Definition of TreeNode: class TreeNode: def __init__(self, val): self.val = val self.left, self.right = None, None "&q

zstu.4191: 无向图找环(dfs树 + 邻接表)

4191: 无向图找环 Time Limit: 5 Sec  Memory Limit: 128 MB Submit: 117  Solved: 34 Description 给你一副无向图,每条边有边权,保证图联通,现在让你判断这个图是否有异或值大于零的环存在. Input 多组测试数据,每组先输入两个数n m,表示图的点跟边的数量. 然后是m行,每行三个数a b c.代表一条边的起点,终点,边权. 1 <= n<= 100000, 1 <= m <= 200000. 1 <

【BZOJ4424】Cf19E Fairy DFS树

[BZOJ4424]Cf19E Fairy Description 给定 n 个点,m 条边的无向图,可以从图中删除一条边,问删除哪些边可以使图变成一个二分图. Input 第 1 行包含两个整数 n,m.分别表示点数和边数.第 2 到 m+1 行每行两个数 x,y 表示有一条(x,y)的边. Output 输出第一行一个整数,表示能删除的边的个数.接下来一行按照从小到大的顺序输出边的序号. Sample Input 4 4 1 2 1 3 2 4 3 4 Sample Output 4 1 2