dfs樹


dfs樹是解決圖中帶環的利器。

前天CF的F題就是dfs樹,但是當時我沒有認真思考 覺着找到一個環過於困難 當時沒有想到 也沒理解dfs樹的意義。

對於一張無向圖求出一個dfs樹 這個樹有兩種邊 樹邊和非樹邊。

其中非樹邊連接的u v 他們一定具有祖先關系。

$注:這是一個很顯然 也十分重要的性質。

應用:CF1325F Ehab's Last Theorem

給出一張無向聯通圖 且不存在重邊 自環。定義\(m=\lceil sqrt(n)\rceil\)

求出圖中一個環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}\rceil\)個點 可以證明這個東西>=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和最大。路徑可以經過同一條邊同一個點 不過這樣的路徑的價值被計算相應次數。

顯然一條路徑出現兩次相當於沒出現。如何求這樣的路徑。可以考慮線性基求最大值。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM