[cf1656I]Neighbour Ordering

显然每个点双独立,不妨分别考虑(特判两点一边的情况):

必要条件1:任意两点间不存在三条长度$\ge 2$且两两不交的简单路径

若存在,记点集分别为$\{a_{i}\},\{b_{i}\}$和$\{c_{i}\}$,用$[x_{1}<_{x_{2}}x_{3}]$表示"方向"

根据抽屉原理,存在两条路径"方向"相同,进而两者所构成的环即矛盾

必要条件2:原图(指点双)存在哈密顿回路

若不存在,取最长的简单环,并取一条形如$(环上,环外)$的边$(A,B)$

删去$A$后,取$B$到环上极近(不经过环上其余点)的点$C$,并分类讨论:

1.若$A$与$C$相邻,则可以将$(A,B)+(B\rightarrow C)$加入其中,与环最长矛盾

2.若$A$与$C$不相邻,则$A$和$C$间存在$\begin{cases}环上的两条路径\\(A,B)+(B\rightarrow C)\end{cases}$,不满足必要条件1,矛盾

求出哈密顿回路后,将所有点按回路的顺序重新编号

充要条件:不存在两条边$(i_{1},i_{2})$和$(j_{1},j_{2})$,满足$i_{1}<j_{1}<i_{2}<j_{2}$

充分性:若不存在,将每个点的出边按顺时针距离依次编号即可

必要性:若存在,对其分类讨论——

1.若仅有这$4$个点(即为$K_{4}$​),不妨假设$2 <_{1}3<_{1}4$

分析三元环$(2-)1-3-2$,可得$1<_{3}2$

分析四元环$4-1-3-2$,注意到同时有$3<_{1}4$和$1<_{3}2$,即矛盾

2.若存在其余点,不妨假设某点在$i_{1}$到$j_{1}$的路径上

此时,$i_{1}$和$j_{1}$间存在$\begin{cases}(i_{1},i_{1}+1)+...+(j_{1}-1,j_{1})\\(i_{1},i_{2})+(i_{2},i_{2}-1)+...+(j_{1}+1,j_{1})\\(i_{1},i_{1}-1)+...+(j_{2}+1,j_{2})+(j_{2},j_{1})\end{cases}$,不满足必要条件1,矛盾

条件的判定和解的构造均简单,问题即如何求哈密顿回路:

在合法的图中,总存在一个二度点,将该点删除并连接相邻两点

重复此过程(直至两点一边),以这两点基础,依次将删除的点插入回路即可

而在不合法的图中,总会出现以下两种情况之一:

1.最终未得到两点一边的情况

2.某次插入时,(删除时)所相邻的两点在回路中不相邻

以此判定即可,时间复杂度为$o(n\log n)$,可以通过

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 300005
 4 int t,n,m,q,x,y,tmp,dfn[N],low[N],st[N],bl[N],K[N],nex[N],id[N];
 5 vector<int>e[N],V[N],ans[N];vector<pair<int,int> >E[N];
 6 pair<int,int>adj[N];queue<int>Q;set<int>S[N];
 7 bool cmp(int x,int y){
 8     return ((tmp<id[x])==(tmp<id[y]) ? id[x]<id[y] : tmp<id[x]);
 9 }
10 void dfs(int k,int fa){
11     dfn[k]=low[k]=++dfn[0],st[++st[0]]=k;
12     for(int i:e[k])
13         if (i!=fa){
14             if (dfn[i])low[k]=min(low[k],dfn[i]);
15             else{
16                 dfs(i,k),low[k]=min(low[k],low[i]);
17                 if (dfn[k]<=low[i]){
18                     V[++q]=vector<int>{k};
19                     while (V[q].back()!=i){
20                         bl[st[st[0]]]=q;
21                         V[q].push_back(st[st[0]--]);
22                     }
23                 }
24             }
25         }
26 }
27 int main(){
28     scanf("%d",&t);
29     while (t--){
30         scanf("%d%d",&n,&m);
31         for(int i=1;i<=n;i++)e[i].clear();
32         for(int i=1;i<=m;i++){
33             scanf("%d%d",&x,&y),x++,y++;
34             e[x].push_back(y),e[y].push_back(x);
35         }
36         q=0;
37         for(int i=0;i<=n;i++)dfn[i]=0;
38         for(int i=1;i<=n;i++)
39             if (!dfn[i])dfs(i,0);
40         for(int i=1;i<=q;i++)E[i].clear();
41         for(int i=1;i<=n;i++)
42             for(int j:e[i])
43                 if (dfn[i]>dfn[j])E[bl[i]].push_back(make_pair(i,j));
44         bool flag=0;
45         for(int i=1;i<=n;i++)ans[i].clear();
46         for(int i=1;i<=q;i++){
47             for(int j:V[i])e[j].clear(),S[j].clear();
48             for(pair<int,int> j:E[i]){
49                 x=j.first,y=j.second;
50                 e[x].push_back(y),e[y].push_back(x);
51                 S[x].insert(y),S[y].insert(x);
52             }
53             K[0]=0;
54             for(int j:V[i])
55                 if (S[j].size()==2)Q.push(j);
56             while (!Q.empty()){
57                 int k=Q.front();Q.pop();
58                 if (S[k].size()!=2)continue;
59                 x=(*S[k].begin()),y=(*++S[k].begin());
60                 K[++K[0]]=k,adj[K[0]]=make_pair(x,y);
61                 S[k].clear(),S[x].erase(k),S[y].erase(k);
62                 S[x].insert(y),S[y].insert(x);
63                 if (S[x].size()==2)Q.push(x);
64                 if (S[y].size()==2)Q.push(y);
65             }
66             if (K[0]+2!=V[i].size()){flag=1;break;}
67             x=y=0;
68             for(int j:V[i]){
69                 nex[j]=j;
70                 if (S[j].size()==1)(x ? y : x)=j;
71             }
72             nex[x]=y,nex[y]=x;
73             for(int j=K[0];j;j--){
74                 int k=K[j],x=adj[j].first,y=adj[j].second;
75                 if (nex[x]!=y)swap(x,y);
76                 if (nex[x]!=y){flag=1;break;}
77                 nex[x]=k,nex[k]=y;
78             }
79             if (flag)continue;
80             for(int j=V[i][0],k=0;k<V[i].size();j=nex[j],k++)id[j]=k;
81             for(int j:V[i]){
82                 tmp=id[j],sort(e[j].begin(),e[j].end(),cmp);
83                 for(int k:e[j])ans[j].push_back(k);
84             }
85         }
86         if (flag)printf("NO\n");
87         else{
88             printf("YES\n");
89             for(int i=1;i<=n;i++){
90                 for(int j:ans[i])printf("%d ",j-1);
91                 printf("\n");
92             }
93         }
94     }
95     return 0;
96 } 
View Code

 

posted @ 2022-07-28 10:07  PYWBKTDA  阅读(89)  评论(0编辑  收藏  举报