[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;
}