POJ 2438 哈密顿回路

Children's Dining
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 4730 Accepted: 754 Special Judge

Description

Usually children in kindergarten like to quarrel with each other. This situation annoys the child-care women. For instant, when diner time comes, a fierce conflict may break out when a certain couple of children sitting side by side who are hostile with each other. Although there aren't too many children dining at the same round table, but the relationship of "enemy" or "friend" may be very complex. The child-care women do come across a big problem. Now it is time for you to help them to figure out a proper arrangement of sitting, with which no two "enemy" children is adjacent. 

Now we assume that there are 2 * n children who sit around a big table, and that none has more than n - 1 "enemies".

Input

The input is consisted of several test blocks. For each block, the first line contains two integers n and m (1 <= n <= 200, 0 <= m <= n (n - 1)). We use positive integers from 1 to 2 * n to label the children dining round table. Then m lines followed. Each contains positive integers i and j ( i is not equal to j, 1 <= i, j <= 2 * n), which indicate that child i and child j consider each other as "enemy". In a input block, a same relationship isn't given more than once, which means that if "i j" has been given, "j i" will not be given. 

There will be a blank line between input blocks. And m = n = 0 indicates the end of input and this case shouldn't be processed.

Output

For each test block, if the proper arrangement exist, you should print a line with a proper one; otherwise, print a line with "No solution!".

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

 

转载于:https://www.cnblogs.com/stranger-/p/9385306.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
自动控制节水灌溉技术的高低代表着农业现代化的发展状况,灌溉系统自动化水平较低是制约我国高效农业发展的主要原因。本文就此问题研究了单片机控制的滴灌节水灌溉系统,该系统可对不同土壤的湿度进行监控,并按照作物对土壤湿度的要求进行适时、适量灌水,其核心是单片机和PC机构成的控制部分,主要对土壤湿度与灌水量之间的关系、灌溉控制技术及设备系统的硬件、软件编程各个部分进行了深入的研究。 单片机控制部分采用上下位机的形式。下位机硬件部分选用AT89C51单片机为核心,主要由土壤湿度传感器,信号处理电路,显示电路,输出控制电路,故障报警电路等组成,软件选用汇编语言编程。上位机选用586型以上PC机,通过MAX232芯片实现同下位机的电平转换功能,上下位机之间通过串行通信方式进行数据的双向传输,软件选用VB高级编程语言以建立友好的人机界面。系统主要具有以下功能:可在PC机提供的人机对话界面上设置作物要求的土壤湿度相关参数;单片机可将土壤湿度传感器检测到的土壤湿度模拟量转换成数字量,显示于LED显示器上,同时单片机可采用串行通信方式将此湿度值传输到PC机上;PC机通过其内设程序计算出所需的灌水量和灌水时间,且显示于界面上,并将有关的灌水信息反馈给单片机,若需灌水,则单片机系统启动鸣音报警,发出灌水信号,并经放大驱动设备,开启电磁阀进行倒计时定时灌水,若不需灌水,即PC机上显示的灌水量和灌水时间均为0,系统不进行灌水。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值