为防止广告,目前nocow只有登录用户能够创建新页面。如要创建页面请先登录/注册(新用户需要等待1个小时才能正常使用该功能)。

Sgu/122

来自NOCOW
< Sgu
跳转到: 导航, 搜索

求满足Ore条件的图的哈密尔顿回路.(题目所说的条件强于Ore条件,Ore条件是,对于一个无向图,任意两个互异不相邻的点的度数(去除自环和重边)和不小于点数).算法: (1)随意找到一条路.goto (2). (2)如果这条路的首尾相邻且路长 != n(n为顶点数),goto (a);若首尾相邻且路长==n,输出;否则,先将此路向两侧延伸至无法延伸,goto (3). (a)随便找出一条连接路中顶点和路外顶点的边,把它加入路,并从路中删去一条和新加入的边相邻的边,从而使得路变成一个更长的路. (3)设路径为a-k1-k2-...-km-b,找到路中一个顶点kj,要求满足a和kj相邻且k(j-1)和b相邻.这样删除边k(j-1)-kj,加入边a-kj和k(j-1)-b,从而使得路变成一个首尾相邻的等长的路. 证明:首先,满足Ore条件的图是连通的.设图中有n个点.否则若图不连通,则可以分为两个互不连通部分,分别有s个点和(n-s)个点.我们任取这两个互不连通部分中各一点,它们的度数和最多s-1+n-s-1=n-2<n.这不满足Ore条件.得证. 既然满足Ore条件的图是连通的,(2)算法总可以成功找到这样一条边. 再证明(3).由于这个路是不能再延伸的,所以路的头尾两点发出的边都指向路中的点,且这两个点的度数和>=n(这两个点一定不相邻,见(2)).(3)中可能成为j的下标有2...m这m-1个,由于m-1<n,由抽屉原理,总存在满足条件的j. 这样整个算法就能正确的执行.每次(3)开始之前都一定要延伸路径,强烈提示注意.

//P*M
#include<cstdio>
#include<cstring>
char ch1;
bool map[1001][1001], f[1001], flag;
int hd, tl, p, n, x, found, p1, cl, q[1001], suc[1001];
int main(){
  freopen("sgu122.in", "r", stdin);
  freopen("sgu122.out", "w", stdout);
  scanf("%d", &n);
  memset(map, false, sizeof(map));
  for(int i = 1; i <= n; i++){
    scanf("%d", &x);
    map[i][x] = true;
    map[x][i] = true;
    scanf("%c", &ch1);
    while(ch1 != '\n' && !feof(stdin)){scanf("%d", &x); map[i][x] = true; map[x][i] = true; scanf("%c", &ch1);}
  }
  hd = 1; tl = 1; memset(suc, 0, sizeof(suc)); found = 1;
  memset(f, true, sizeof(f));
  f[1] = false;   
  flag = true;
  while(flag){
    flag = false;
    for(int i = 1; i <= n; i++){
      if(map[tl][i] && f[i]){flag = true; suc[tl] = i; tl = i; f[i] = false; found++; break;}
    }
  }
  flag = true;
  while(flag){
    flag = false;
    for(int i = 1; i <= n; i++){
      if(map[hd][i] && f[i]){flag = true; suc[i] = hd; hd = i; f[i] = false; found++; break;}
    }
  }
  while(true){
    if(map[hd][tl] == true){
      if(found == n){
	suc[tl] = hd;
	printf("1 ");
	p = 1;
	for(int i = 1; i <= n; i++){
	  printf("%d ", p = suc[p]);
	}
	printf("\n");
	break;
      }else{
        p = hd;
        while(true){
          flag = false;
          for(int i = 1; i <= n; i++){
	    if(f[i] && map[p][i]){
	      suc[tl] = hd;
	      hd = suc[p];
	      suc[p] = i;
	      tl = i;
	      f[i] = false;
	      ++found;
	      flag = true;
	      break;
	    }
          }
          if(flag){break;}
          p = suc[p];
        }     
        flag = true;
        while(flag){
          flag = false;
          for(int i = 1; i <= n; i++){
            if(map[tl][i] && f[i]){flag = true; suc[tl] = i; tl = i; f[i] = false; found++; break;}
          }
        }
        flag = true;
        while(flag){
          flag = false;
          for(int i = 1; i <= n; i++){
            if(map[hd][i] && f[i]){flag = true; suc[i] = hd; hd = i; f[i] = false; found++; break;}
          }
        }   
      }
    }else{
      p = hd;
      while(true){
	if(map[hd][suc[p]] && map[tl][p]){
	  break;
	}
	p = suc[p];
      }
      p1 = suc[p];
      cl = 0;
      while(p1 != tl){q[++cl] = p1; p1 = suc[p1];}
      for(int i = cl; i >= 1; i--){
        suc[suc[q[i]]] = q[i];
      }
      suc[suc[p]] = 1;
      suc[p] = tl;
      tl = q[1];
    }
  }
  fclose(stdin);
  fclose(stdout);
  return 0;
}
/by Logic
#include<stdio.h>
#include<algorithm>
using namespace std;
const int maxn=1050;
int n,st,en,l;
bool bel[maxn]={0};
int co[maxn]={0};
bool e[maxn][maxn]={0};
int pr[maxn],ne[maxn];
bool add(int x,bool su)
{
	int i,j;
	for(i=1;i<=n;i++)
		if(e[x][i]&&!bel[i]) 
		{
			for(j=1;j<=n;j++) 
				if(e[i][j]) co[j]=i;
			if(!su) ne[i]=x,pr[x]=i,st=i;
			else ne[x]=i,pr[i]=x,en=i;
			bel[i]=1;
			l++;
			return 1;
		}
	return 0;
}
int main()
{
#ifndef ONLINE_JUDGE
	freopen("data.in","r",stdin);
#endif
	int i,j,t;
	char ci;
	scanf("%d",&n);
	for(i=1;i<=n;i++)
	{
		scanf("%d",&t);
		if(i==1) en=t;
		e[i][t]=1;
		ci=getchar();
		while(ci!='\n'&&ci!='\r'&&ci!=EOF)
			scanf("%d",&t),e[i][t]=1,ci=getchar();
	}
	st=1,l=2;
	bel[st]=bel[en]=1;
	ne[st]=en,pr[en]=st;
	while(1)
	{
		while(add(st,0));
		while(add(en,1));
		if(e[st][en])
		{
			if(l==n) {ne[en]=st,pr[st]=en;break;}
			for(i=1;i<=n;i++)
				if(!bel[i]&&co[i])
				{
					ne[en]=st,pr[st]=en;
					st=i,en=pr[co[i]];
					ne[st]=co[i],pr[co[i]]=st;
					bel[i]=1,l++;
					break;
				}
		}
		else 
			for(i=ne[st];ne[i]!=en;i=ne[i])
			{
				if(e[i][en]&&e[st][ne[i]]) 
				{
					for(j=en;j!=i;j=ne[j])
						swap(pr[j],ne[j]);
					t=ne[i];
					ne[i]=en,pr[en]=i;
					en=t;
					break;
				}
			}
	}
	for(i=1;i!=pr[1];i=ne[i])
		printf("%d ",i);
	printf("%d %d\n",pr[1],1);
	return 0;
}
个人工具