zoukankan      html  css  js  c++  java
  • dfs树

    dfs树是解决图中带环的利器。

    前天CF的F题就是dfs树,但是当时我没有认真思考 觉着找到一个环过于困难 当时没有想到 也没理解dfs树的意义。

    对于一张无向图求出一个dfs树 这个树有两种边 树边和非树边。

    其中非树边连接的u v 他们一定具有祖先关系。

    $注:这是一个很显然 也十分重要的性质。

    应用:CF1325F Ehab's Last Theorem

    给出一张无向联通图 且不存在重边 自环。定义(m=lceil sqrt(n) ceil)

    求出图中一个环S 满足S是一个简单环 且(|S|geq m)

    或者求出图中一个independent set W 满足 W=m

    求环或者求独立集 我们考虑一张无向图 很难求出最大的独立集 但是只是让求出一个大小为m的独立集。

    考虑如何求环 dfs树。但是求不了最大环 但是我们要的也不是最大。我们利用非树边判断环的大小。

    由于没有重边 自环 所以一个点连出w条非树边 那么显然有大小为w+1的环。

    如果所有点都没有构成大小>=m的环 那说明每个点都最多有 m-2条非树边。

    这个时候考虑最大独立集 当前点我们加入到我们的集合中 然后其最多影响m-2个点。

    把能影响的都给标记了 最后我们发现最多能选 (lceil frac{n}{m-1} ceil)个点 可以证明这个东西>=m.证毕。

    所以我们直接上dfs树即可。值得注意的是 最后构造独立集的时候 需要从叶子节点构造。

    可以证明 这样对其他节点的影响如上面的分析一样。

    const int MAXN=200010;
    int n,m,len=1,w,top,flag,cc;
    int vis[MAXN],s[MAXN],d[MAXN],mark[MAXN],q[MAXN];
    int lin[MAXN],ver[MAXN<<1],nex[MAXN<<1];
    inline void add(int x,int y)
    {
    	ver[++len]=y;nex[len]=lin[x];lin[x]=len;
    	ver[++len]=x;nex[len]=lin[y];lin[y]=len;
    }
    inline void dfs(int x,int las)
    {
    	if(flag)return;
    	vis[x]=1;s[++top]=x;
    	go(x)
    	{
    		if((i^1)==las)continue;
    		if(flag)break;
    		if(!vis[tn])
    		{
    			d[tn]=d[x]+1;
    			dfs(tn,i);
    		}
    		else if(d[x]-d[tn]+1>=w)
    		{
    			put(2);
    			put(d[x]-d[tn]+1);
    			int ww=d[x]-d[tn]+1;
    			while(ww)
    			{
    				printf("%d ",s[top]);
    				--top;--ww;
    			}
    			flag=1;
    		}
    	}
    	--top;
    	if(!mark[x])
    	{
    		q[++cc]=x;
    		go(x)mark[tn]=1;
    	}
    }
    
    int main()
    {
    	freopen("1.in","r",stdin);
    	get(n);get(m);
    	rep(1,m,i)add(read(),read());
    	w=(int)ceil(sqrt(n*1.0));
    	//put(w);
    	dfs(1,-1);
    	if(flag)return 0;
    	put(1);rep(1,w,i)printf("%d ",q[i]);
    	return 0;
    }
    

    当然dfs树还有应用 如上次我写了一道bzoj 的电压 那道题是真的比较妙 dfs树上差分。最后证明的是 其他环都是无效的 有dfs树上的环即可。

    一道例题:LINK:2115 Wc2011 Xor

    给出一张有向无环图 求出1~n的一条路径使得其xor和最大。路径可以经过同一条边同一个点 不过这样的路径的价值被计算相应次数。

    显然一条路径出现两次相当于没出现。如何求这样的路径。可以考虑线性基求最大值。

  • 相关阅读:
    Xamarin.Android开发实践(十八)
    Xamarin.Android开发实践(十七)
    smokeping网络监控
    Cobbler自动化部署
    在线编辑器KindEditor的使用
    前端之快速创建标签
    Tornado之自定义异步非阻塞的服务器和客户端
    算法基础知识之树、二叉树
    Tornado之实例和扩展
    Scrapy源码研究前戏
  • 原文地址:https://www.cnblogs.com/chdy/p/12506181.html
Copyright © 2011-2022 走看看