ORE性质,任意两个互异不相邻的点的度的和大于等于n(去除重边和自环),即deg(u)+deg(v)>=n。
详细资料:http://www.nocow.cn/index.php/Sgu/122,http://blog.csdn.net/volzkzg/article/details/7514103
解决方法就是: 从一点开始向两边扩展,直至不能扩展,然后连成环,判断点数是否为n,若不为n,则在环外任意找与该环相连的一点进行增广,然后重复扩展连环过程。
PS:SGU卡常数,卡输入绝了... = =|||,把递归子程序换成循环,输入换成getchar输入才过... 其实主要原因还是在输入上,试了三种输入方法,时间分别173ms,343ms,562ms(也就是超时,= =|||)
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
bool adj[1105][1105],visited[1105];
int l[1105],r[1105],listnum,head,tail,n;
//void FindHead()
//{
// int i;
// bool flag=true;
// while(flag)
// {
// flag=false;
// for(i=1;i<=n;++i)
// {
// if(!visited[i]&&adj[head][i])
// {
// l[head]=i;
// r[i]=head;l[i]=0;
// visited[i]=true;
// listnum++;
// head=i;
// flag=true;
// }
// }
// }
//}
//void FindTail()
//{
// int i;
// bool flag=true;
// while(flag)
// {
// flag=false;
// for(i=1;i<=n;++i)
// {
// if(!visited[i]&&adj[tail][i])
// {
// r[tail]=i;
// l[i]=tail;r[i]=0;
// visited[i]=true;
// listnum++;
// tail=i;
// flag=true;
// }
// }
// }
//}
//void Reverse()
//{
// if(adj[head][tail])
// {
// l[head]=tail;
// r[tail]=head;
// return ;
// }
// int i,j;
// for(i=r[head];r[i]!=tail;i=r[i])
// {
// if(adj[head][r[i]]&&adj[tail][i])
// {
// l[head]=r[head];r[head]=r[i];
// l[r[i]]=head;
// r[tail]=i;
// r[i]=l[i];l[i]=tail;
// tail=l[head];
// for(j=r[i];j!=head;j=r[j])
// {
// swap(l[j],r[j]);
// }
// return ;
// }
// }
//}
//void Add()
//{
// int i,j,num=0,p=head,pos;
// for(i=1;i<=n;++i)
// {
// if(!visited[i])
// {
// pos=i;
// visited[i]=true;
// break;
// }
// }
// for(i=head;;i=r[i])
// {
// if(adj[i][pos])
// {
// l[r[i]]=0;
// head=r[i];
// r[i]=pos;
// l[pos]=i;r[pos]=0;
// tail=pos;
// listnum++;
// return ;
// }
// }
//}
//void Print()
//{
// int i;
// for(i=1;r[i]!=1;i=r[i])
// {
// printf("%d ",i);
// }
// printf("%d 1\n",i);
//}
//void Work()
//{
// while(1)
// {
// FindHead();
// FindTail();
// if(listnum==n)
// {
// Reverse();
// Print();
// return ;
// }
// Reverse();
// Add();
// }
//}
void Work()
{
int i,j,k,pos;
bool flag;
while(1)
{
flag=true;
while(flag)
{
flag=false;
for(i=1;i<=n;++i)
{
if(!visited[i]&&adj[head][i])
{
l[head]=i;
r[i]=head;l[i]=0;
visited[i]=true;
listnum++;
head=i;
flag=true;
}
}
}
flag=true;
while(flag)
{
flag=false;
for(i=1;i<=n;++i)
{
if(!visited[i]&&adj[tail][i])
{
r[tail]=i;
l[i]=tail;r[i]=0;
visited[i]=true;
listnum++;
tail=i;
flag=true;
}
}
}
if(adj[head][tail])
{
l[head]=tail;
r[tail]=head;
}
else
{
for(i=r[head];r[i]!=tail;i=r[i])
{
if(adj[head][r[i]]&&adj[tail][i])
{
l[head]=r[head];r[head]=r[i];
l[r[i]]=head;
r[tail]=i;
r[i]=l[i];l[i]=tail;
tail=l[head];
for(j=r[i];j!=head;j=r[j])
{
swap(l[j],r[j]);
}
break;
}
}
}
if(listnum==n)
{
for(i=1;r[i]!=1;i=r[i])
{
printf("%d ",i);
}
printf("%d 1\n",i);
return ;
}
else
{
for(i=1;i<=n;++i)
{
if(!visited[i])
{
pos=i;
visited[i]=true;
break;
}
}
for(i=head;;i=r[i])
{
if(adj[i][pos])
{
l[r[i]]=0;
head=r[i];
r[i]=pos;
l[pos]=i;r[pos]=0;
tail=pos;
listnum++;
break;
}
}
}
}
}
void Init()
{
memset(adj,false,sizeof(adj));
memset(visited,false,sizeof(visited));
char ch;
scanf("%d",&n);
int i,j;
for(i=1;i<=n;++i)
{
scanf("%d",&j);
adj[i][j]=adj[j][i]=true;
ch=getchar();
while(ch!='\n'&&ch!=EOF)
{
scanf("%d",&j);
adj[i][j]=adj[j][i]=true;
ch=getchar();
}
}
listnum=head=tail=1;
visited[1]=true;
}
int main()
{
Init();
Work();
return 0;
}