首页 > 其他 > 详细

【NOIP模拟】种树

时间:2018-10-30 13:00:41      阅读:215      评论:0      收藏:0      [点我收藏+]

题面

Fanvree 很聪明,解决难题时他总会把问题简单化。例如,他就整天喜欢把图转化为树。但是他不会缩环,那他怎么转化呢? 这是一个有 n个点 m 条双向边的图,Fanvree 会选定一个节点,然后删掉这个节点和这个点连出去的边,如果变成了一棵树,那么这个节点便是可行的,什么是树呢?树也即无简单环的无向连通图。

告诉 Fanvree 可能的节点是什么。

对于 40%的数据:n,m<=1000;
另外存在 10%的数据:m=n-1;
另外存在 20%的数据:m=n;
对于 100%的数据:n,m<=100000

分析

这道水题告诉我,太自信会出事!出大事!

你看那40分的数据,枚举删哪个点dfs检验一下就过了,那10%的,说明不是个联通的图,找一下哪个点是单独的就过了。那20%,说明是树上加了个边,找一下就行了。这就70了!!

而我坚信自己写的是对的,缩了个点,然后删去一个点,剩下n-1个点,因此剩下n-2条边,需要删去m-(n-2)条边,只要找度数为这个就没错了吧?

然而我跑去缩点,缩了点再在那个环里找度数为m-(n-2)的边,完美错过正解。

其实根本不用缩点,只需要判一下割点,因为割点一定不在环内啊!!!!(显然,树上的每一个点都是割点)而环内可能有割点

哎。。。

代码

  1. #include<bits/stdc++.h>  
  2. using namespace std;  
  3. #define N 100010  
  4. #define RT register  
  5. int n,m,t,cnt,tot,gro,cot,mark,root,child;  
  6. int dfn[N],low[N],deg[N],cut[N],ans[N],first[N];  
  7. struct email  
  8. {  
  9.     int u,v;  
  10.     int nxt;  
  11. }e[N*4];  
  12. template<class T>  
  13. inline void read(T &x)  
  14. {  
  15.     x=0;int f=1;static char ch=getchar();  
  16.     while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}  
  17.     while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}  
  18.     x*=f;  
  19. }  
  20. inline void add(int u,int v)  
  21. {  
  22.     e[++cnt].nxt=first[u];first[u]=cnt;  
  23.     e[cnt].u=u;e[cnt].v=v;  
  24. }  
  25.   
  26. inline void tarjan(int u,int fa)  
  27. {  
  28.     dfn[u]=low[u]=++tot;  
  29.     for(RT int i=first[u];i;i=e[i].nxt)  
  30.     {  
  31.         int v=e[i].v;  
  32.         if(v==fa)continue;  
  33.         if(!dfn[v])  
  34.         {  
  35.             tarjan(v,u);  
  36.             low[u]=min(low[u],low[v]);  
  37.             if(low[v]>=dfn[u]&&u!=root)   
  38.                 cut[u]=1;  
  39.             if(u==root)child++;  
  40.         }     
  41.         else  
  42.             low[u]=min(low[u],dfn[v]);    
  43.     }  
  44.     if(child>1&&u==root)cut[u]=1;  
  45. }  
  46.   
  47. int main()  
  48. {  
  49.     read(n);read(m);  
  50.     for(RT int i=1;i<=m;i++)  
  51.     {  
  52.         int u,v;  
  53.         read(u),read(v);  
  54.         add(u,v);add(v,u);  
  55.         deg[u]++,deg[v]++;  
  56.     }  
  57.     for(int i=1;i<=n;i++)  
  58.         if(!deg[i])  
  59.         {root=i;break;}  
  60.     for(RT int i=1;i<=n;i++)  
  61.         if(!dfn[i])  
  62.             tarjan(i,i);  
  63.     for(RT int i=1;i<=n;i++)  
  64.         if(deg[i]==(m-(n-2))&&!cut[i])  
  65.             ans[++cot]=i;  
  66.     printf("%d\n",cot);  
  67.     for(RT int i=1;i<=cot;i++)printf("%d ",ans[i]);  
  68.     return 0;  
  69. }   

【NOIP模拟】种树

原文:https://www.cnblogs.com/NSD-email0820/p/9876108.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!