题意与分析

一条很有趣的题目。给一个无向图,问它是否无环,且可以在上面找到一条线,使所有的顶点要么在线上要么不在线上但在与线相连的边上。

那么首先要确定所有点联系在一起。这个可以同判环一起处理:如果建图新加入的点同原先的点含有同一个祖先,那它肯定是环没跑了。然后遍历所有节点,看看是否拥有同一个祖先。这样就完成了两个任务。

接下来需要一点分析:我们可以证明,这条线(如果存在)一定是树的直径,或者是与树的直径长度相等(在端点差一个点那边分的叉)。为什么?如果这条线不是树的直径,那么长度一定小于直径,且树的直径与它的交点一定至少会延伸出两个点,那么这就一定会翻车,这条线一定不会满足条件。所以如果有一条线满足这个条件,那它必须得是树的直径。然后就是之前知识学习的地方,先找树的直径(这里需要记录端点,我没有采用栈的方法记录,采用了一种比较简单的方法解决),然后判断非树直径的点是否度数为1即可。

这题综合考察了树的几个性质,非常适合学习/复习。比如说我竟然忘了并查集怎么判环- -

代码

/*
* Filename: poj3310.cpp
* Date: 2018-11-05
*/
#include <iostream>
#include <cstring>
#include <vector> #define INF 0x3f3f3f3f
#define PB push_back
#define MP make_pair
#define fi first
#define se second
#define rep(i,a,b) for(repType i=(a); i<=(b); ++i)
#define per(i,a,b) for(repType i=(a); i>=(b); --i)
#define ZERO(x) memset(x, 0, sizeof(x))
#define MS(x,y) memset(x, y, sizeof(x))
#define ALL(x) (x).begin(), (x).end() #define QUICKIO \
ios::sync_with_stdio(false); \
cin.tie(0); \
cout.tie(0);
#define DEBUG(...) fprintf(stderr, __VA_ARGS__), fflush(stderr) using namespace std;
typedef int repType; const int MAXN=105;
vector<int> G[MAXN]; int pa[MAXN],n;
int find_pa(int x)
{
return pa[x]==x?x:pa[x]=find_pa(pa[x]);
}
bool union_pa(int x,int y)
{
int fx=find_pa(x),
fy=find_pa(y);
if(fx!=fy) pa[fx]=fy;
else return false;
return true;
} bool judge_cnt()
{
int cnt=0;
rep(i,1,n)
if(pa[find_pa(i)]==i) cnt++;
return cnt==1;
} int dep[MAXN];
void dfs(int x)
{
rep(i,0,int(G[x].size())-1)
if(dep[G[x][i]]==-1)
{
dep[G[x][i]]=dep[x]+1;
dfs(G[x][i]);
}
}
bool on_road[MAXN];
bool on_road_tmp[MAXN];
int maxdep=0;
void dfs2(int now, int ndep)
{
if(ndep>=maxdep)
{
memcpy(on_road,on_road_tmp,sizeof(on_road));
maxdep=ndep;
} rep(i,0,int(G[now].size())-1)
if(dep[G[now][i]]==-1)
{
dep[G[now][i]]=dep[now]+1;
on_road_tmp[G[now][i]]=true;
dfs2(G[now][i],ndep+1);
on_road_tmp[G[now][i]]=false;
}
} int
main()
{
int kase=0;
while(cin>>n)
{
if(!n) break;
rep(i,1,n) G[i].clear();
rep(i,1,n) pa[i]=i;
int e; cin>>e;
bool has_loop=false;
rep(i,1,e)
{
int u,v; cin>>u>>v;
G[u].PB(v);
G[v].PB(u);
if(find_pa(u)!=find_pa(v)) union_pa(u,v);
else has_loop=true;
}
if(e>n-1) has_loop=true;
bool ok=true;
if(has_loop || !judge_cnt())
ok=false;
if(ok)
{
MS(dep,-1);
dep[1]=0;
dfs(1);
int pnt_id=1;
maxdep=0;
rep(i,1,n) if(dep[pnt_id]<dep[i])
{
pnt_id=i;
maxdep=dep[pnt_id];
}
ZERO(on_road_tmp);
MS(dep,-1);
dep[pnt_id]=0;
on_road_tmp[pnt_id]=true;
dfs2(pnt_id, 0);
rep(i,1,n)
if(!on_road[i]&&G[i].size()!=1)
{
ok=false; break;
}
}
if(ok) cout<<"Graph "<<++kase<<" is a caterpillar."<<endl;
else cout<<"Graph "<<++kase<<" is not a caterpillar."<<endl;
}
return 0;
}

「日常训练」Caterpillar(POJ-3310)的更多相关文章

  1. 「日常训练」ZgukistringZ(Codeforces Round #307 Div. 2 B)

    题意与分析(CodeForces 551B) 这他妈哪里是日常训练,这是日常弟中弟. 题意是这样的,给出一个字符串A,再给出两个字符串B,C,求A中任意量字符交换后(不限制次数)能够得到的使B,C作为 ...

  2. 「日常训练」 Fire!(UVA-11624)

    与其说是训练不如说是重温.重新写了Java版本的代码. import java.util.*; import java.math.*; import java.io.BufferedInputStre ...

  3. 「日常训练」COMMON 约数研究(HYSBZ-1968)

    题意与分析 感谢https://www.cnblogs.com/Leohh/p/7512960.html的题解.这题话说原来不在我的训练范围,正好有个同学问我,我就拿来做做.数学果然不是我擅长的啊,这 ...

  4. 「日常训练」Mike and Feet(Codeforces Round #305 Div. 2 D)

    题意 (Codeforces 548D) 对一个有$n$个数的数列,我们要求其连续$x(1\le x\le n)$(对于每个$x$,这样的连续group有若干个)的最小数的最大值. 分析 这是一道用了 ...

  5. 「日常训练」「小专题·图论」 Frogger (1-1)

    题意 分析 变形的dijkstra. 分析题意之后补充. 代码 // Origin: // Theme: Graph Theory (Basic) // Date: 080518 // Author: ...

  6. 「日常训练」 Mike and Fun (CFR305D2B)

    题意(CodeForces 548B) 每次对01矩阵中的一位取反,问每次操作后,单列中最长连续1的长度. 分析 非常非常简单,但是我当时训练的时候WA了四次...无力吐槽了,人间 不值得.jpg 代 ...

  7. 「日常训练」Common Subexpression Elimination(UVa-12219)

    今天做的题目就是抱佛脚2333 懂的都懂. 这条题目干了好几天,最后还是参考别人的代码敲出来了,但是自己独立思考了两天多,还是有收获的. 思路分析 做这条题我是先按照之前的那条题目(The SetSt ...

  8. 「日常训练」Magic Stones(CodeForces-1110E)

    题意 给定两个数组c和t,可以对c数组中的任何元素变换\(c_i\)​成\(c_{i+1}+c_{i-1}-c_i\)​,问c数组在若干次变换后能否变换成t数组. 分析 这种魔法题目我是同样的没做过. ...

  9. 「日常训练」Jongmah(Codeforces-1110D)

    题意 你有n个数字,范围[1, m],你可以选择其中的三个数字构成一个三元组,但是这三个数字必须是连续的或者相同的,每个数字只能用一次,问这n个数字最多构成多少个三元组? 分析 根据官方Editori ...

随机推荐

  1. HDU 6464 免费送气球 【权值线段树】(广东工业大学第十四届程序设计竞赛)

    传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6464 免费送气球 Time Limit: 2000/1000 MS (Java/Others)    M ...

  2. BZOJ 3289: Mato的文件管理 【莫队 + 树状数组】

    任意门:https://www.lydsy.com/JudgeOnline/problem.php?id=3289 3289: Mato的文件管理 Time Limit: 40 Sec  Memory ...

  3. SQL 查询函数

    1.abs函数取值(绝对值) select ABS(-20) 结果是20 2.ceiling函数取大于等于指定表达式的最小整数 select CEILING(40.5) 结果是41 3.floor函数 ...

  4. OC对象里面包含的结构体类型的属性,不能对该结构体属性的成员单个进行修改

    OC对象里面包含的结构体类型的属性,不能对该结构体属性的成员单个进行修改,需要对OC对象的结构体属性整体赋值. 关于网上很多博客写着“结构体类型里面的某个属性如果想要修改是不允许单个修改的” 之解释: ...

  5. 【Cmd命令行】基础—findstr与for循环

    Findstr命令 findstr是Window系统自带的命令,用途是查找指定的一个或多个文件文件中包含(或通过参数 /V来控制不包含)某些特定字符串的行,并将该行完整的信息打印出来,或者打印查询字符 ...

  6. JAVA正则表达式校验qq号码

    /* * 校验qq号码* 要求必须是5-15位* 0不能开头* 必须都是数字 */ (1)使用正则表达式校验qq号码 (2)方式2

  7. Knowledge Point 20180303 对比编译器、解释器与Javac编译原理

    编译器与Javac编译原理 在前文我们知道了Java是一种编译语言和解释语言,它的源代码经过编译器Javac编译为能够被JVM识别的二进制语言,然后JVM将其解释为能够被平台识别的机器语言.那么什么是 ...

  8. Sftp搭建与配置参考

    Sftp搭建与配置参考 1. 介绍 sftp是Secure File Transfer Protocol的缩写,安全文件传送协议.可以为传输文件提供一种安全的加密方法.sftp 与 ftp 有着几乎一 ...

  9. c#随便聊聊数据库操作

    最近在学习web后台以及Python,到了程序员的转折年纪了,哎.估计很久不会写博文了.言归正传. 在原理的数据库连接池HiKari项目上.我扩展了独立的3个库,说是3个库,其实原本该是一个库.先聊聊 ...

  10. javascript中sort()排序的一些理解

    sort()方法对一个数组进行排序,并可以接受一个比较函数,最后返回一个排序的数组. 1.sort()有自身默认的比较函数,该函数把排序的元素都看作字符串. var s = [5, 4, 3, 2, ...