注意!注意!前方高能!本题卡常!!!

我们发现,所有的狗血剧情都在告诉我们,树的话直接dfs就出来了

那么基环树呢?

其实只要暴力删边,理论上的复杂度是可以过的qwq

但是删哪条边呢?

这里要引出一个基环树的常用操作:拓扑排序求环。具体方法是:在基环树上拓扑排序,然后拓扑序列中不存在的节点就是环中的节点了。

最后要用到环中的边的时候有一个小技巧,就是存边的时候(我用的是邻接表存双向边)按


input(x,y,z);
if(x>y) swap(x,y);
add(x,y,z);add(y,x,z);

的顺序存。

这样找边去重的时候就比较好找。。。(我也表述不太明白,具体看代码吧~)

Code


#include<iostream>
#include<cstdio>
#include<queue> using namespace std; const int N = 1e5+1;
int n,m,r[N];
int h[N],cnt,delu,delv;//假装 del_u-v 这条边已经被删去了qwq
struct edge
{
int nxt;
int to;
}e[N];
int ans[N],ans1[N];
int qh=0,qt=1,qtp[N],tp[N],vis[N],visu[N],visv[N],tpcnt;//巨丑的代码qwq inline void readx(int &x)
{
x=0;char ch=getchar();
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+ch-48;ch=getchar();}
} inline void add(register int u,register int v)
{
e[++cnt].nxt=h[u];
e[cnt].to=v;
h[u]=cnt;
} inline void topo()
{
for(register int i=1;i<=n;++i) vis[i]=1;
for(register int u=1;u<=n;++u)
{
for(register int i=h[u];i;i=e[i].nxt)
{
register int v=e[i].to;
++tp[u];++tp[v];
}
}
for(register int i=1;i<=n;++i) if(tp[i]==2) qtp[qt++]=i; // for(int i=1;i<=n;++i) printf("%d ",qtp[i]);printf("\n"); while(qt>qh)
{
register int u=qtp[++qh];vis[u]=0;
for(register int i=h[u];i;i=e[i].nxt)
{
register int v=e[i].to;
tp[u]-=2;tp[v]-=2;
if(tp[v]==2&&vis[v]) qtp[qt++]=v;
}
}
for(register int u=1;u<=n;++u)
if(vis[u]==1)
{
for(register int i=h[u];i;i=e[i].nxt)
{
register int v=e[i].to;
if(vis[v]==1&&u<v)
{
visu[++tpcnt]=u;visv[tpcnt]=v;
}
}
}
} inline void update()
{
for(register int i=1;i<=n;++i)
{
if(ans1[i]==ans[i]) continue;
if(ans[i]==0) {for(register int j=1;j<=n;++j) ans[j]=ans1[j];return;}
if(ans1[i]>ans[i]) return;
//ans1[i]<ans[i]
for(register int j=i;j<=n;++j) ans[j]=ans1[j];return;
}
} inline void dfs(register int u,register int fa)
{
ans1[++cnt]=u;
priority_queue <int,vector<int>,greater<int> > q;//小根堆
for(register int i=h[u];i;i=e[i].nxt)
{
register int v=e[i].to;
if(v==fa||(u==delu&&v==delv)||(u==delv&&v==delu)) continue;
q.push(v);
}
while(!q.empty())
{
register int v=q.top();q.pop();
dfs(v,u);
}
} signed main()
{
readx(n);readx(m);
for(register int i=1;i<=m;++i)
{
int u,v;readx(u);readx(v);
if(u>v) swap(u,v);
add(u,v);add(v,u);
}
cnt=0;
if(m==n-1)
{
dfs(1,0);
for(register int i=1;i<=n;++i) ans[i]=ans1[i];
}
else
{
topo();
for(register int i=1;i<=tpcnt;++i)
{
cnt=0;
delu=visu[i];delv=visv[i];
dfs(1,0);
update();
}
}
for(register int i=1;i<=n;++i)
printf("%d ",ans[i]);
return 0;
}

其实代码也就是看106行到107行那里,别的地方写得太丑了没法看,而且自己基本能写出来,加油哦qwq!

最新文章

  1. CSS 3学习——边框
  2. fluent-ffmpeg 常用函数
  3. thinkphp3.2跨控制器调用其他模块的方法
  4. μC/OS-Ⅲ系统的时间管理函数和定时器
  5. 2015年12月10日 spring初级知识讲解(三)Spring消息之activeMQ消息队列
  6. 【Android】cocos2d-x-3.1.1环境搭建与创建工程( Win7 32位系统)
  7. IOS学习之路十七(通过delegate进行页面传值)
  8. Mysql Innodb体系结构
  9. css为超过一定宽度的文本内容自动加上省略号
  10. python转lua最容易掉进去的坑--作用域
  11. jsp假分页
  12. idea环境配置
  13. Winfrom DataGridView中使用Tooltip
  14. Page页面生命周期——微信小程序
  15. 独立的android开发者开发app如何盈利?
  16. rhel7配置yum的方法
  17. 增加kms计数
  18. WebSettings 文档 API 翻译 常用设置
  19. [OS] 远程启动计划任务时以管理员身份运行
  20. 20155212 实验一《Java开发环境的熟悉》实验报告

热门文章

  1. Spring Boot整合EhCache
  2. PHP+Mysql防止SQL注入的方法
  3. 集合转换为数组toArray(),数组转换为集合asList()
  4. awk命令_Linux awk 命令用法详解
  5. C:字符数组 与 字符串
  6. wordpress Error establishing a database connection问题
  7. BZOJ - 2038 小Z的袜子(普通莫队)
  8. java NIO - DirectBuffer 和 HeapBuffer
  9. Django框架之模板路径及静态文件路径配置
  10. Mongodb 分片原理