题目:http://acm.hdu.edu.cn/showproblem.php?pid=4337
题目感觉用深搜,
#include <stdio.h>
#include <string.h>
#define MAX 200
int n,m,step;
int map[MAX][MAX];
int visit[MAX];
bool pass[MAX],flag;
void dfs(int x,int step)
{
int i,j;
pass[x]=true;
if(step==n&&map[x][1]==1)
{
flag=true;
return ;
}
if(flag||step==n)
return ;
for(i=1;i<=n&&!flag;i++)
{
if(map[x][i]==1&&!flag&&!pass[i])
{
visit[step+1]=i;
dfs(i,step+1);
if(!flag)
pass[i]=false;
}
}
}
int main()
{
int a,b,i,j;
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(pass,false,sizeof(pass));
memset(map,0,sizeof(map));
for(i=1;i<=m;i++)
{
scanf("%d%d",&a,&b);
map[a][b]=map[b][a]=1;
}
step=1;
flag=false;
visit[step]=1;
dfs(1,1);
if(flag)
{
for(i=n;i>1;i--)
printf("%d ",visit[i]);
printf("%d\n",visit[1]);
}
else
printf("no solution\n");
}
return 0;
}
标程,题解:自己感觉不是很理解,,,但在这里写一下
构造一个特殊图的Hamilton回路。首先随机得到一个环序列a1, a2, ..., an, 如果a(i)->a(i+1)在图中没有边,因为每个点至少和一半的点有边相连,于是一定可以找到另一个点j,满足a(i)-a(j)有边,a(i+1)-a(j+1)有边。然后反转环中a(i+1)到a(j)这一段序列,即可令环上存在的边数增加1或2(取决于原来的环上a(j)->a(j+1)是否有边)。继续此过程直到环上所有的边都存在。
#include <cstdio>
#include <algorithm>
#include <cassert>
#include <cstring>
const int MAXN = 160;
int mp[MAXN][MAXN];
int ans[MAXN], n, deg[MAXN];
void rev(int L, int R) {
while (L != R) {
std::swap(ans[L], ans[R]);
if (++L == n) L = 0;
if (L == R) break;
if (--R == -1) R = n - 1;
}
}
int solve() {
int i, j;
for (i = 0 ; i < n ; i++) {
if (mp[ans[i]][ans[(i+1)%n]] == 0) break;
}
if (i == n) return 0; // done
for (j = 0 ; j < n ; j++) {
if (j == i || j == (i+1)%n || (j+1)%n == i) continue;
if (mp[ans[i]][ans[j]] && mp[ans[(i+1)%n]][ans[(j+1)%n]]) {
// printf("rev(%d,%d)\n",(i+1)%n,j);
rev((i+1)%n, j);
return 1;
}
}
assert(false);
return 1;
}
int main() {
freopen("data.in","r",stdin);
freopen("data.out","w",stdout);
int m, ca = 0;
while (scanf("%d%d",&n,&m) != EOF) {
memset(mp, 0, sizeof(mp));
memset(deg, 0, sizeof(deg));
while (m--) {
int t1, t2;
scanf("%d%d",&t1,&t2);
--t1; --t2;
assert(t1 != t2 && mp[t1][t2] == 0);
mp[t1][t2] = mp[t2][t1] = 1;
++deg[t1];
++deg[t2];
}
for (int i = 0 ; i < n ; i++)
assert(deg[i] >= (n+1) / 2);
for (int i = 0 ; i < n ; i++)
ans[i] = i;
int cnt = 0;
while (solve());
for (int i = 0 ; i < n ; i++)
printf("%d ",ans[i]+1);
printf("\n");
}
return 0;
}