bzoj 2935 [Poi1999]原始生物——欧拉回路思路!
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2935
有向图用最小的路径(==总点数最少)覆盖所有边。
完了完了我居然连1999年的题都做不出来了。
TJ:https://blog.csdn.net/u014609452/article/details/53705451
仔细一想,原来就是欧拉回路的连通块自然不用说,原来不是欧拉回路的连通块,我们在走路径的时候不时从一个点跳到另一个点,其实可以看作是给这两个点间连了一条边!
所以手动连一个欧拉回路。这样应该一定是最小的。
因为是欧拉回路,所以有点浪费。因为其实欧拉路就可以了,只是我们不会连成欧拉路罢了。
考虑把自己连的一条边当做路径的开始或结尾,这样就可以不走那条边,从而变成欧拉路。体现在答案上就是少了一个点,点数==删边前边数。
TJ的代码实现这一过程写得太好啦!无耻默写。
所以需要回顾!
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int N=1000; int n,sum,deg[N+5],fa[N+5],ans; bool tag[N+5],vis[N+5]; int find(int a){return fa[a]==a?a:fa[a]=find(fa[a]);} int main() { for(int i=1;i<=N;i++)fa[i]=i; scanf("%d",&n);int x,y;ans=n;//原边数 for(int i=1;i<=n;i++) { scanf("%d%d",&x,&y); vis[x]=1;vis[y]=1; deg[x]++;deg[y]--; if(find(x)!=find(y))fa[find(x)]=find(y); } for(int i=1;i<=N;i++) if(vis[i]&°[i])tag[find(i)]=1; for(int i=1;i<=N;i++) if(vis[i]&&fa[i]==i&&!tag[i])ans++;//原欧拉回路+1 for(int i=1;i<=N;i++) sum+=(deg[i]>0?deg[i]:-deg[i]);//补的边 ans+=sum/2; printf("%d",ans); return 0; }