Description
Up to thirty couples will attend a wedding feast, at which they will be seated on either side of a long table. The bride and groom sit at one end, opposite each other, and the bride wears an elaborate headdress that keeps her from seeing people on the same side as her. It is considered bad luck to have a husband and wife seated on the same side of the table. Additionally, there are several pairs of people conducting adulterous relationships (both different-sex and same-sex relationships are possible), and it is bad luck for the bride to see both members of such a pair. Your job is to arrange people at the table so as to avoid any bad luck.
Input
The input consists of a number of test cases, followed by a line containing 0 0. Each test case gives n, the number of couples, followed by the number of adulterous pairs, followed by the pairs, in the form "4h 2w" (husband from couple 4, wife from couple 2), or "10w 4w", or "3h 1h". Couples are numbered from 0 to n - 1 with the bride and groom being 0w and 0h.
Output
For each case, output a single line containing a list of the people that should be seated on the same side as the bride. If there are several solutions, any one will do. If there is no solution, output a line containing "bad luck".
Sample Input
10 6 3h 7h 5w 3w 7h 6w 8w 3w 7h 3w 2w 5h 0 0
Sample Output
1h 2h 3w 4h 5h 6h 7h 8h 9h
Source
Waterloo Local Contest, 2007.9.29
题意:一对夫妻举行婚礼,有最多30对夫妻参加,其中新娘新郎必须坐在桌子两侧。新娘看不到她所在一侧的人, 只能看到对面的人。新娘看到一对夫妻坐在一边是不吉利的。除此之外,有些人又通奸关系。看到有通奸关系的人左一边也是不吉利的。求出新娘一侧坐的人。
思路:由于选择坐在左侧和右侧,我们可以选择2at算法;
坐在新娘一侧,我们先假设新娘一定坐在左侧,我们就此可以画出关系图;
此题需要注意的是新郎也可以有通奸关系,我们需要特别处理;
此题跟hdu1814相似,看不懂代码的可以先去看看;
此代码输出的是字典序最小的;
i表示坐在左侧;i+num表示坐在右侧;
代码:
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int N=100004; struct node{ int now,next; }str[N]; int head[N],tot; int vis[N],top,s[N]; void add(int x,int y) { str[tot].now=y; str[tot].next=head[x]; head[x]=tot++; } bool dfs(int u,int n) { if(vis[u+n]) return false; if(vis[u]) return true; vis[u]=1; s[top++]=u; for(int i=head[u];i!=-1;i=str[i].next) { int v=str[i].now; if(!dfs(v,n)) return false; } return true; } bool ok(int n) { for(int i=0;i<n;i++) { if(!vis[i]&&!vis[i+n]) { top=0; if(!dfs(i,n)) { while(top>0) { vis[s[--top]]=0; } if(!dfs(i+n,n)) return false; } } } return true; } int main() { int n,m; while(~scanf("%d%d",&n,&m)) { if(n==0&&m==0) break; tot=0; int num=2*n; memset(vis,0,sizeof(vis)); memset(head,-1,sizeof(head)); add(0,1+num); //新娘假设必须坐在左侧 add(1,1+num); add(num,0); add(1+num,0); for(int i=2;i<2*n;i+=2) { add(i,i+1+num); add(i+1+num,i); add(i+1,i+num); add(i+num,i+1); } char c[100]; getchar(); for(int i=0;i<m;i++) { int a=0,b=0,len; gets(c); for(len=0;c[len]-'0'>=0&&c[len]-'0'<=9;len++) a=a*10+c[len]-'0'; if(c[len]=='h') a=2*a+1; else a=2*a; if(c[len+1]==' ') len+=2; else len++; for(;len<strlen(c)-1;len++) b=b*10+c[len]-'0'; if(c[len]=='h') b=2*b+1; else b=2*b; if(a==1) //如果是新郎特殊考虑 add(b+num,b); //a是新郎肯定坐在右侧,b做在右侧必然产生矛盾; else if(b==1) //同上 add(a+num,a); else { add(a+num,b); add(b+num,a); } } if(!ok(2*n)) printf("bad luck\n"); else { for(int i=2;i<2*n;i++) if(vis[i]) //vis记录与新娘满足关系的点,i表示坐在左侧则与新娘同侧; { if(i==2*n-2||i==2*n-2) { if(i%2==0) printf("%dw\n",i/2); else printf("%dh\n",i/2); break; } if(i%2==0) printf("%dw ",i/2); else printf("%dh ",i/2); } } } }