• 【NOIP2018】旅行


    一句话题意:
    从一号点,可以回溯,但不能重新经过之前经过的节点
    问走完所有点,最后走到n,走出的节点序的字典序最小是多少
    

    由于图可能是一棵树或者一棵基环树,所以重点基本都在基环树上

    NOIP的D2T1的原数据范围还是很小的,直接枚举环上断每一条边的最小答案即可

    然而cz搞了一个数据加强版,显而易见就只能用(Theta(nlog n))的复杂度跑了

    具体的方式是:走到环的入口的时候,判断一下节点大小关系,分情况讨论

    这样可以避免很多无脑断边的情况

    代码:

    #include<bits/stdc++.h>
    #define N 500005
    using namespace std;
    
    int n,m,u,v;
    
    struct Edge
    {
    	int next,to;
    }edge[N<<1];
    int cnt=0,head[N];
    
    inline void add_edge(int from,int to)
    {
    	edge[++cnt].next=head[from];
    	edge[cnt].to=to;
    	head[from]=cnt;
    }
    
    template<class T>inline void read(T &res)
    {
    	char c;T flag=1;
    	while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
    	while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
    }
    
    bool book[N],cir[N],hav;
    int fa[N];
    void dfs1(int u,int fa)
    {
    	book[u]=1;
    	for(register int i=head[u];i;i=edge[i].next)
    	{
    		int v=edge[i].to;
    		if(v==fa) continue;
    		if(book[v])
    		{
    			hav=cir[u]=cir[v]=1;
    			return;
    		}
    		dfs1(v,u);
    		if(hav&&cir[v])
    		{
    			if(cir[u]) hav=0;
    			cir[u]=1;
    			return;
    		}
    	}
    }
    
    queue<int> ans;
    void dfs2(int u,int pos)
    {
    	if(book[u]) return;
    	book[u]=1;
    	ans.push(u);
    	priority_queue<int,vector<int>,greater<int> > qq;
    	for(register int i=head[u];i;i=edge[i].next)
    	{
    		int v=edge[i].to;
    		if(v==fa[u]) continue;
    		if(book[v]) continue;
    		qq.push(v);
    	}
    	while(!qq.empty())
    	{
    		int now=qq.top();
    		qq.pop();
    		if(!hav&&cir[now]&&now>pos&&qq.empty())
    		{
    			hav=1;
    			return;
    		}
    		int nxt=-0x3f3f3f3f;
    		if(!qq.empty()&&cir[u]) nxt=qq.top();
    		if(nxt==-0x3f3f3f3f) nxt=pos;
    		dfs2(now,nxt);
    	}
    }
    
    int main()
    {
    	read(n);read(m);
    	for(register int i=1;i<=m;++i)
    	{
    		read(u);read(v);
    		add_edge(u,v);
    		add_edge(v,u);
    	}
    	dfs1(1,1);
    	memset(book,0,sizeof(book));
    	hav=0;
    	dfs2(1,0x3f3f3f3f);
    	while(!ans.empty())
    	{
    		printf("%d ",ans.front());
    		ans.pop();
    	}
    	return 0;
    }
    
    /*
    6 6
    1 2
    2 3
    2 4
    2 5
    3 6
    4 6
    */
    

    另外,这份代码好像有点问题,因为之前脑子一抽设的fa数组根本没更新
    后面dfs2还用到了……
    但是影响不大,还是可以A

  • 相关阅读:
    C# 序列化技术详解《转》
    DataGridView中的DataGridViewComboBoxColumn使用浅析
    取EXCEL文件的3种方法
    教你几种在SQLServer中删除重复数据方法
    事件浅析
    迭代委托链
    C#调用耗时函数时显示进度条浅探
    启动公告【过时】
    在Web应用中接入微信支付的流程之极简清晰版
    VBoxManage: error: Cannot register the hard disk 解决办法
  • 原文地址:https://www.cnblogs.com/tqr06/p/11794809.html
Copyright © 2020-2023  润新知