Last Corollary CodeForces - 1364D(dfs树找最小环)

2024-02-01 13:48

本文主要是介绍Last Corollary CodeForces - 1364D(dfs树找最小环),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

思路:对于所给的图形来说,可以分为树图和非树图。
两种图的做法不一样,因为树图是没有环的,只有第二种选择。
对于树图来说,我们找出树的每一层有哪几个点,并且保存起来。然后分别查看(0,2,4…)层的总数和(1,3,5…)层的总数,哪一个符合就输出哪一个就行。
对于非树图来讲,就比较麻烦了。
首先我们先找出非树图中最小的环来,假如这个环的长度为len. 如果len<=k的话,那么我们把这个环的点输出就可以了。如果len>k的话,我们可以发现,对于一个长度为len的环,不相邻的点一共有len/2(下取整)个。也就是说,我们找出非树图中最小的环,就一定可以得到符合题意的答案。
那么接下来就是怎么去找非树图的最小环了。具体的我就不赘述了,简而言之就是将一个图先当做树去遍历,记录每一个点出现的次序,如果发现了这个点之前出现的话,就可以直接计算出这个环的长度,然后我们不断的更新最小值,记录一下这个环上面的一个点就行。在dfs的时候记录一下每一个点的先驱节点是什么,方便后面输出。
代码如下:

#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;const int maxx=1e5+100;
const int maxm=2e5+100;
struct node{int to,next;
}e[maxm<<1];
int head[maxm<<1];
int vis[maxx],dis[maxx],f[maxx];
vector<int> q[maxx];
int n,m,k,tot,ans=inf,pos;inline void init()
{tot=0;memset(head,-1,sizeof(head));memset(dis,0,sizeof(dis));memset(vis,0,sizeof(vis));
}
inline void add(int u,int v)
{e[tot].next=head[u],e[tot].to=v,head[u]=tot++;
}
inline int dfs(int u,int fa,int id)
{dis[u]=id;vis[u]=1;f[u]=fa;for(int i=head[u];i!=-1;i=e[i].next){int to=e[i].to;if(to==fa) continue;if(vis[to]) //这个点之前遍历过,就说明出现了环{if(ans>abs(dis[to]-dis[u])+1){ans=abs(dis[to]-dis[u])+1;pos=u;}}else dfs(to,u,id+1);}
}
inline void Dfs(int u,int f,int h)
{q[h].push_back(u);for(int i=head[u];i!=-1;i=e[i].next){int to=e[i].to;if(to==f) continue;Dfs(to,u,h+1);}
}
int main()
{scanf("%d%d%d",&n,&m,&k);init();int x,y;for(int i=1;i<=m;i++){scanf("%d%d",&x,&y);add(x,y);add(y,x);}if(m==n-1){cout<<1<<endl;Dfs(1,0,0);int sumj=0,sumo=0;int i=0;while(q[i].size()){if(i%2==0) sumj+=q[i].size();else sumo+=q[i].size();i++;}int num=(k+1)/2;if(sumj>=num){for(int i=0;;i+=2){for(int j=0;j<q[i].size();j++){cout<<q[i][j]<<" ";num--;if(!num) break;}if(!num) break;}}else{for(int i=1;;i+=2){for(int j=0;j<q[i].size();j++){cout<<q[i][j]<<" ";num--;if(!num) break;}if(!num) break;}}return 0;}vector<int> p;dfs(1,0,0);if(ans<=k){cout<<2<<endl<<ans<<endl;for(int i=1;i<=ans;i++) cout<<pos<<" ",pos=f[pos];cout<<endl;}else{int num=k/2+(k%2==1);cout<<1<<endl;int cnt=0;for(;num;num--){cout<<pos<<" ";pos=f[pos];pos=f[pos];}cout<<endl;}return 0;
}

努力加油a啊,(o)/~

这篇关于Last Corollary CodeForces - 1364D(dfs树找最小环)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/667478

相关文章

windos server2022里的DFS配置的实现

《windosserver2022里的DFS配置的实现》DFS是WindowsServer操作系统提供的一种功能,用于在多台服务器上集中管理共享文件夹和文件的分布式存储解决方案,本文就来介绍一下wi... 目录什么是DFS?优势:应用场景:DFS配置步骤什么是DFS?DFS指的是分布式文件系统(Distr

poj 1258 Agri-Net(最小生成树模板代码)

感觉用这题来当模板更适合。 题意就是给你邻接矩阵求最小生成树啦。~ prim代码:效率很高。172k...0ms。 #include<stdio.h>#include<algorithm>using namespace std;const int MaxN = 101;const int INF = 0x3f3f3f3f;int g[MaxN][MaxN];int n

poj 1287 Networking(prim or kruscal最小生成树)

题意给你点与点间距离,求最小生成树。 注意点是,两点之间可能有不同的路,输入的时候选择最小的,和之前有道最短路WA的题目类似。 prim代码: #include<stdio.h>const int MaxN = 51;const int INF = 0x3f3f3f3f;int g[MaxN][MaxN];int P;int prim(){bool vis[MaxN];

poj 2349 Arctic Network uva 10369(prim or kruscal最小生成树)

题目很麻烦,因为不熟悉最小生成树的算法调试了好久。 感觉网上的题目解释都没说得很清楚,不适合新手。自己写一个。 题意:给你点的坐标,然后两点间可以有两种方式来通信:第一种是卫星通信,第二种是无线电通信。 卫星通信:任何两个有卫星频道的点间都可以直接建立连接,与点间的距离无关; 无线电通信:两个点之间的距离不能超过D,无线电收发器的功率越大,D越大,越昂贵。 计算无线电收发器D

poj 1734 (floyd求最小环并打印路径)

题意: 求图中的一个最小环,并打印路径。 解析: ans 保存最小环长度。 一直wa,最后终于找到原因,inf开太大爆掉了。。。 虽然0x3f3f3f3f用memset好用,但是还是有局限性。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#incl

hdu 2489 (dfs枚举 + prim)

题意: 对于一棵顶点和边都有权值的树,使用下面的等式来计算Ratio 给定一个n 个顶点的完全图及它所有顶点和边的权值,找到一个该图含有m 个顶点的子图,并且让这个子图的Ratio 值在所有m 个顶点的树中最小。 解析: 因为数据量不大,先用dfs枚举搭配出m个子节点,算出点和,然后套个prim算出边和,每次比较大小即可。 dfs没有写好,A的老泪纵横。 错在把index在d

hdu 1102 uva 10397(最小生成树prim)

hdu 1102: 题意: 给一个邻接矩阵,给一些村庄间已经修的路,问最小生成树。 解析: 把已经修的路的权值改为0,套个prim()。 注意prim 最外层循坏为n-1。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstri

poj 3050 dfs + set的妙用

题意: 给一个5x5的矩阵,求由多少个由连续6个元素组成的不一样的字符的个数。 解析: dfs + set去重搞定。 代码: #include <iostream>#include <cstdio>#include <set>#include <cstdlib>#include <algorithm>#include <cstring>#include <cm

poj 2175 最小费用最大流TLE

题意: 一条街上有n个大楼,坐标为xi,yi,bi个人在里面工作。 然后防空洞的坐标为pj,qj,可以容纳cj个人。 从大楼i中的人到防空洞j去避难所需的时间为 abs(xi - pi) + (yi - qi) + 1。 现在设计了一个避难计划,指定从大楼i到防空洞j避难的人数 eij。 判断如果按照原计划进行,所有人避难所用的时间总和是不是最小的。 若是,输出“OPETIMAL",若

poj 2135 有流量限制的最小费用最大流

题意: 农场里有n块地,其中约翰的家在1号地,二n号地有个很大的仓库。 农场有M条道路(双向),道路i连接着ai号地和bi号地,长度为ci。 约翰希望按照从家里出发,经过若干块地后到达仓库,然后再返回家中的顺序带朋友参观。 如果要求往返不能经过同一条路两次,求参观路线总长度的最小值。 解析: 如果只考虑去或者回的情况,问题只不过是无向图中两点之间的最短路问题。 但是现在要去要回