标签:bee n个元素 blank NPU gem mil print ring turn
Time Limit: 1000MS | Memory Limit: 65536K | |||
Total Submissions: 4730 | Accepted: 754 | Special Judge |
Description
Input
Output
Sample Input
1 0 2 2 1 2 3 4 3 6 1 2 1 3 2 4 3 5 4 6 5 6 4 12 1 2 1 3 1 4 2 5 2 6 3 7 3 8 4 8 4 7 5 6 5 7 6 8 0 0
Sample Output
1 2 4 2 3 1 1 6 3 2 5 4 1 6 7 2 3 4 5 8
解析 题目说保证 每个点的度数等于n所以 一定存在哈密顿回路 然后在他给出的图的补图上求一个哈密顿回路就可以了 套一个O(n*n)的板子。
哈密顿图:存在哈密顿回路的图
哈密顿图的判定:
一:Dirac定理(充分条件)
设一个无向图中有N个顶点,若所有顶点的度数大于等于N/2,则哈密顿回路一定存在.(N/2指的是?N/2?,向上取整)
二:基本的必要条件
设图G=<V, E>是哈密顿图,则对于v的任意一个非空子集S,若以|S|表示S中元素的数目,G-S表示G中删除了S中的点以及这些点所关联的边后得到的子图,则W(G-S)<=|S|成立.其中W(G-S)是G-S中联通分支数.
三:竞赛图(哈密顿通路)
N(N>=2)阶竞赛图一点存在哈密顿通路.
AC代码
1 #include <stdio.h> 2 #include <string.h> 3 using namespace std; 4 const int maxn = 500+10; 5 bool visit[maxn]; 6 int mapp[maxn][maxn],ans[maxn]; 7 int n,m; 8 inline void _reverse(int s, int t) //将数组anv从下标s到t的部分的顺序反向 9 { 10 int temp; 11 while(s < t) 12 { 13 temp = ans[s]; 14 ans[s] = ans[t]; 15 ans[t] = temp; 16 s++; 17 t--; 18 } 19 } 20 void Hamilton(int n) 21 { 22 memset(visit,false,sizeof(visit)); 23 int s = 1, t;//初始化取s为1号点 24 int ansi = 2; 25 int i, j; 26 int w; 27 int temp; 28 for(i = 1; i <= n; i++) if(mapp[s][i]) break; 29 t = i;//取任意邻接与s的点为t 30 visit[s] = visit[t] = true; 31 ans[0] = s; 32 ans[1] = t; 33 while(true) 34 { 35 while(true) //从t向外扩展 36 { 37 for(i = 1; i <= n; i++) 38 { 39 if(mapp[t][i] && !visit[i]) 40 { 41 ans[ansi++] = i; 42 visit[i] = true; 43 t = i; 44 break; 45 } 46 } 47 if(i > n) break; 48 } 49 w = ansi - 1;//将当前得到的序列倒置,s和t互换,从t继续扩展,相当于在原来的序列上从s向外扩展 50 i = 0; 51 _reverse(i, w); 52 temp = s; 53 s = t; 54 t = temp; 55 while(true) //从新的t继续向外扩展,相当于在原来的序列上从s向外扩展 56 { 57 for(i = 1; i <= n; i++) 58 { 59 if(mapp[t][i] && !visit[i]) 60 { 61 ans[ansi++] = i; 62 visit[i] = true; 63 t = i; 64 break; 65 } 66 } 67 if(i > n) break; 68 } 69 if(!mapp[s][t]) //如果s和t不相邻,进行调整 70 { 71 for(i = 1; i < ansi - 2; i++)//取序列中的一点i,使得ans[i]与t相连,并且ans[i+1]与s相连 72 if(mapp[ans[i]][t] && mapp[s][ans[i + 1]])break; 73 w = ansi - 1; 74 i++; 75 t = ans[i]; 76 _reverse(i, w);//将从ans[i +1]到t部分的ans[]倒置 77 }//此时s和t相连 78 if(ansi == n) return;//如果当前序列包含n个元素,算法结束 79 for(j = 1; j <= n; j++) //当前序列中元素的个数小于n,寻找点ans[i],使得ans[i]与ans[]外的一个点相连 80 { 81 if(visit[j]) continue; 82 for(i = 1; i < ansi - 2; i++)if(mapp[ans[i]][j])break; 83 if(mapp[ans[i]][j]) break; 84 } 85 s = ans[i - 1]; 86 t = j;//将新找到的点j赋给t 87 _reverse(0, i - 1);//将ans[]中s到ans[i-1]的部分倒置 88 _reverse(i, ansi - 1);//将ans[]中ans[i]到t的部分倒置 89 ans[ansi++] = j;//将点j加入到ans[]尾部 90 visit[j] = true; 91 } 92 } 93 int main() 94 { 95 while(scanf("%d%d",&n,&m)!=EOF) 96 { 97 if(n==0)break; 98 n*=2; 99 memset(mapp,0,sizeof(mapp)); 100 for(int i=1;i<=n;i++) 101 for(int j=1;j<=n;j++) 102 mapp[i][j]=i==j?0:1; 103 for(int i=0;i<m;i++) 104 { 105 int u,v; 106 scanf("%d%d",&u,&v); 107 mapp[u][v]=mapp[v][u]=0; 108 } 109 Hamilton(n); 110 printf("%d",ans[0]); 111 for(int i=1;i<=n-1;i++) 112 { 113 printf(" %d",ans[i]); 114 } 115 printf("\n"); 116 } 117 }
该算法的详细过程及哈密顿回路的其他知识
https://www.cnblogs.com/Ash-ly/p/5452580.html
标签:bee n个元素 blank NPU gem mil print ring turn
原文地址:https://www.cnblogs.com/stranger-/p/9385306.html