sgu 122. The book 满足ore性质的汉密尔顿回路 难度:2

122. The book

time limit per test: 0.25 sec. 
memory limit per test: 4096 KB

 

There is a group of N (2<=N<=1000) people which are numbered 1 through N, and everyone of them has not less than [ (N+1) / 2 ] friends. A man with number 1 has the book, which others want to read. Write the program which finds a way of transferring the book so that it will visit every man only once, passing from the friend to the friend, and, at last, has come back to the owner. Note: if A is a friend of B then B is a friend of A.

 

Input

First line of input contains number N. Next N lines contain information about friendships. (i+1)-th line of input contains a list of friends of i-th man.

 

Output

If there is no solution then your program must output 'No solution'.   Else your program must output exactly N+1 number: this sequence should begin and should come to end by number 1, any two neighbours in it should be friends, and any two elements in it, except for the first and last, should not repeat.

 

Sample Input

4
2 3
1 4
1 4
2 3

Sample Output

1 3 4 2 1

1.找到一条不能延伸的路径,此时设左边为st,右边为ed,那么一定满足的性质是,st和ed所能到达的所有点都在这条路上,又由于这个图的性质,两点度数加和一定大于n+1,
根据鸽巢原理,总能找到一个点j,使得j连接ed,nxt[j]连接st,这时候删除j->nxt[j],得到一个环
2.找到一个在环外的点,拆环并且延伸路径
重复这两步直到形成长度为n的环

#include <cstdio>
#include <cstring>
using namespace std;
const int maxn=1001;
int n;
bool vis[maxn],use[maxn];
int  G[maxn][maxn],len[maxn],pre[maxn],nxt[maxn],st,ed;
int predfs(int cnt){
    vis[st]=true;
    for(int i=0;i<len[st];i++){
        int to=G[st][i];
        if(!vis[to]){pre[st]=to;nxt[to]=st;st=to;return predfs(cnt+1);}
    }
    return cnt;
}
int nxtdfs(int cnt){
    vis[ed]=true;
    for(int i=0;i<len[ed];i++){
        int to=G[ed][i];
        if(!vis[to]){nxt[ed]=to;pre[to]=ed;ed=to;return nxtdfs(cnt+1);}
    }
    return cnt;
}
bool getloop(){
    if(st==ed)return true;
    for(int i=0;i<len[ed];i++){
        int to=G[ed][i];
        if(to==st){pre[st]=ed;nxt[ed]=st;return true;}
        for(int j=0;j<len[nxt[to]];j++){
            int jto=G[nxt[to]][j];
            int tt=nxt[to];
            if(jto==st){
                int tmp;
                while(st!=ed){
                    nxt[ed]=to;
                    tmp=pre[to];
                    pre[to]=ed;
                    ed=to;
                    to=tmp;
                }
                nxt[st]=tt;
                pre[tt]=st;
                return true;
            }
        }
    }
    return false;
}
bool breakloop(){
    for(int i=1;i<=n;i++){
        if(!vis[i]){
            for(int j=0;j<len[i];j++){
                if(vis[G[i][j]]){
                        st=i;
                        ed=pre[G[i][j]];
                        nxt[i]=G[i][j];
                        pre[G[i][j]]=st;
                        return true;
                }
            }
        }
    }
    return false;
}
void printloop(){
    int sst=1,tmp=1;
    bool fl=false;
    while(sst!=tmp||!fl){
        printf("%d ",tmp);
        if(nxt[tmp]==tmp)break;
        tmp=nxt[tmp];
        fl=true;
    }
    puts("1");
}
void addedge(int f,int t){
    G[f][len[f]++]=t;
}
int main(){
    scanf("%d",&n);
    getchar();
    for(int i=1;i<=n;i++){
        int tmpt;
        while(scanf("%d",&tmpt)==1){
           if(tmpt!=i)addedge(i,tmpt);
           if(i==1)use[tmpt]=true;
           char ch=getchar();
           if(ch=='\n')break;
        }
    }
    int len=1;
    st=ed=1;
    while(len<n){
        len+=predfs(0);
        len+=nxtdfs(0);
        if(len==n)break;
        if(!getloop())break;
        if(!breakloop())break;
        len++;
    }
    getloop();
    if(len<n)puts("No solution");
    printloop();
    return 0;
}

  

posted @ 2014-10-07 10:51  雪溯  阅读(339)  评论(0编辑  收藏  举报