[POI 2008] CLO-Toll

题意比较清晰不赘述了。
可以想到如果从父亲节点向儿子节点连边的话,树是一个根节点入度为0,其他节点入度为1的图。
所以本题需要求的入度均为1的图即为基环树。
可以想到对于原图的每一个连通块生成一个最小生成树。
枚举每一条节点在一颗生成树上但不在原图上的边,然后统计答案。

还有一种方法是通过dfs遍历每个连通块,利用遇到的第一条返祖边(形成环)来调整父亲指向,确保所有边被覆盖。
dfs判返祖边的做法貌似比较清新易懂一点,但我觉得上面的做法更符合人类直觉。
不过我自己的代码都没调出来。
这里就只放dfs判断返祖边的代码。

#include<bits/stdc++.h> 
using namespace std;
const int N=1e5+1;
int n,m,fa[N];
bool f,t,vis[N];
vector<int>g[N];
void dfs(int u,int uf){
	vis[u]=1;
	for(int v:g[u])if(v!=uf){
		bool nt=t;
		if(vis[v])f=1,t=1;
		else fa[v]=u,dfs(v,u);
		if(nt!=t)fa[u]=v;
	}
}
int main(){
	cin>>n>>m;
	for(int i=0,u,v;i<m;++i)cin>>u>>v,g[u].emplace_back(v),g[v].emplace_back(u);
	for(int i=1;i<=n;++i)
		if(!vis[i]){
			f=0,t=0,dfs(i,0);
			if(!f)cout<<"NIE\n",exit(0);
		}
	cout<<"TAK\n";
	for(int i=1;i<=n;++i)cout<<fa[i]<<'\n';
	return 0;
}
posted @ 2025-08-15 10:27  zhuoheng  阅读(5)  评论(0)    收藏  举报