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; }