[关闭]
@xiaoziyao 2021-08-15T11:39:27.000000Z 字数 2840 阅读 887

CF1477D Nezzar and Hidden Permutations 解题报告

解题报告


CF1477D Nezzar and Hidden Permutations解题报告:

更好的阅读体验

题意

给定一个无向图,将它定向为一个 DAG,求出两个拓扑序让两个拓扑序相同的结点数最少。

分析

埋藏在任务计划的陈年老题。/tuu

首先观察样例,发现很多点都可以拓扑序不相同,我们考虑先求出固定点,然后让其他的结点巧妙地安排顺序使得两个拓扑序不同。

我们发现我们可以每次找到一个与所有点都有连边的点,然后把它删掉,重复这个过程,就可以获得所有固定点,我们钦定它们全部放在最开始的拓扑序。

然后会剩下 个度数不超过 的点,这个性质难以利用,考虑补集转换,那么它的补图每个点度数一定大于

那么我们考虑对每个连通块求出一个 dfs 树,对每棵树进行菊花剖分,然后对于每个菊花都可以安排两种顺序:先中心再四周,先四周再中心,不难发现这样每个点的两个拓扑序一定不相同。

如何进行菊花剖分呢?(我们只需要大小大于 的菊花)我们可以对于每个点 分类讨论:如果它附近有没有划分的点那么直接把 和这些点划分成一个菊花。否则如果 与某一个中心相邻,则将 划分入这个菊花。(注意这里必须判断,原因是菊花剖分的过程中中心可能移动,具体见下方)如果还是不行,考虑与 相邻的这个菊花,如果大小大于 可以直接拿走一个点;否则可以移动这个菊花的中心到另一个点上,并将 放入。

我们发现这样一定会让每个点不重不漏地划分入若干个菊花,时间复杂度

代码

坑点:

  1. #include<stdio.h>
  2. #include<set>
  3. #include<vector>
  4. #include<queue>
  5. #include<map>
  6. using namespace std;
  7. const int maxn=500005;
  8. int T,n,m,tot,cols;
  9. int ans1[maxn],ans2[maxn],deg[maxn],col[maxn],cen[maxn],size[maxn];
  10. vector<int>v[maxn],t[maxn];
  11. set<int>s;
  12. queue<int>q;
  13. map<pair<int,int>,int>mp;
  14. void dfs1(int x,int last){
  15. for(set<int>::iterator it=s.begin();it!=s.end();it++)
  16. if(mp.find(make_pair(*it,x))==mp.end())
  17. t[x].push_back(*it),t[*it].push_back(x);
  18. for(int i=0;i<t[x].size();i++)
  19. if(t[x][i]!=last)
  20. s.erase(t[x][i]);
  21. for(int i=0;i<t[x].size();i++)
  22. if(t[x][i]!=last)
  23. dfs1(t[x][i],x);
  24. }
  25. void dfs2(int x,int last){
  26. if(col[x]==0){
  27. int flg=0;
  28. for(int i=0;i<t[x].size();i++)
  29. if(col[t[x][i]]==0)
  30. flg=1;
  31. if(flg){
  32. col[x]=++cols,cen[cols]=x,size[cols]=1;
  33. for(int i=0;i<t[x].size();i++)
  34. if(col[t[x][i]]==0)
  35. col[t[x][i]]=cols,size[cols]++;
  36. }
  37. else{
  38. if(cen[col[t[x][0]]]==t[x][0])
  39. col[x]=col[t[x][0]],size[col[t[x][0]]]++;
  40. else if(size[col[t[x][0]]]==2)
  41. col[x]=col[t[x][0]],cen[col[t[x][0]]]=t[x][0],size[col[t[x][0]]]++;
  42. else col[x]=++cols,cen[cols]=x,size[cols]=2,size[col[t[x][0]]]--,col[t[x][0]]=cols;
  43. }
  44. }
  45. for(int i=0;i<t[x].size();i++)
  46. if(t[x][i]!=last)
  47. dfs2(t[x][i],x);
  48. }
  49. int main(){
  50. scanf("%d",&T);
  51. while(T--){
  52. scanf("%d%d",&n,&m);
  53. for(int i=1;i<=n;i++)
  54. s.insert(i);
  55. for(int i=1;i<=m;i++){
  56. int x,y;;
  57. scanf("%d%d",&x,&y);
  58. v[x].push_back(y),v[y].push_back(x),deg[x]++,deg[y]++;
  59. mp[make_pair(x,y)]=mp[make_pair(y,x)]=1;
  60. }
  61. for(int i=1;i<=n;i++)
  62. if(deg[i]==n-1)
  63. s.erase(i),q.push(i);
  64. while(!q.empty()){
  65. int x=q.front();
  66. printf("x=%d\n",x);
  67. q.pop(),ans1[x]=ans2[x]=++tot;
  68. for(int i=0;i<v[x].size();i++){//travel all nodes
  69. int y=v[x][i];
  70. deg[y]--;
  71. if(s.find(y)!=s.end()&&deg[y]>=n-tot-1)
  72. s.erase(y),q.push(y);
  73. }
  74. }
  75. for(int i=1;i<=n;i++)
  76. if(s.find(i)!=s.end())
  77. s.erase(i),dfs1(i,0);
  78. for(int i=1;i<=n;i++)
  79. if(col[i]==0&&ans1[i]==0)
  80. dfs2(i,0);
  81. for(int i=1;i<=cols;i++){
  82. ans1[cen[i]]=++tot;
  83. for(int j=0;j<t[cen[i]].size();j++){
  84. int k=t[cen[i]][j];
  85. if(col[k]==i)
  86. ans2[k]=tot,ans1[k]=++tot;
  87. }
  88. ans2[cen[i]]=tot;
  89. }
  90. for(int i=1;i<=n;i++)
  91. printf("%d%c",ans1[i],i==n? '\n':' ');
  92. for(int i=1;i<=n;i++)
  93. printf("%d%c",ans2[i],i==n? '\n':' ');
  94. tot=cols=0,mp.clear();
  95. for(int i=1;i<=n;i++)
  96. deg[i]=col[i]=ans1[i]=0,v[i].clear(),t[i].clear();
  97. }
  98. return 0;
  99. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注