POJ 3648 Wedding(2−SATトポロジ順序付け出力のいずれかの解決策)
テーマリンク:http://poj.org/problem?id=3648
Description
Up to thirty couples will ated a wedding feast、at which they will be seated on eigther side of a long table.The bride and groom sit at one end、opposite each other、and the briide wears s abooraboorate headdress thaat keeps hefrom seeeing people on the same side as her.It isconsideded bad luck ahsband and wifeseaated on the same sime side the the tablble.Additionalle e e thethethetherererepapapapapapapapapapapapapapapadededededededededededededededededededededededededededededederererererererererererererererererererererererererererererererererererererererererepossible)and it is bad luck for the bride to see both members of such a pair.Your job is to arrange people the table so as to avoid any bad luck.
Input
The input consists of a number of test cases、フォローアップby a line containing 0.Each test case gives n,the number of couples,followed by the number of adulterous pairs,followwed by the pairs,in the form“4 h 2 w”(husband from coup le 4,wife from coup 2),or「10 w 4 w」,or「3 h 1 berrow.」 n - 1 with the bride and groom being 0 w and 0 h.
Output
For each case,output a single line containing a list of the people that Shout be seated on the same side as the bride.If there are several solutions,any one will do.If there is solution,output a line containk.back。
Sample Input
Waterloo Local Contact,2007.9.29
件名:
新しいカップルが結婚して、招待されました。 n夫婦に結婚式に行きます。長いテーブルがあります。テーブルの両側にしか座ってはいけません。
以下の要求を満たす必要があります。
1.夫婦は同じ側に座ってはいけません。
2.n夫婦の中には姦通関係(男性、男女、女性を含む)があるかもしれません。姦通関係がある場合は、同時に花嫁の反対側に座ってはいけません。
可能なプログラムがあれば、花嫁と同じ側の人を出力します。
PS:
解を求める時は新郎と同じ側の人を選んで、出力する時は交換して新婦の同じ側の人です。iとjが奸情があるなら、iからj'まで、jからiまでの辺を加えて、新郎の辺に新婦を加えて、必ず新郎を選ぶと表しています。 この問題は花嫁を直接選ぶのは間違いやすいです。花嫁にも浮気があるかもしれないので、排除が必要です。
コードは以下の通りです
Description
Up to thirty couples will ated a wedding feast、at which they will be seated on eigther side of a long table.The bride and groom sit at one end、opposite each other、and the briide wears s abooraboorate headdress thaat keeps hefrom seeeing people on the same side as her.It isconsideded bad luck ahsband and wifeseaated on the same sime side the the tablble.Additionalle e e thethethetherererepapapapapapapapapapapapapapapadededededededededededededededededededededededededededededederererererererererererererererererererererererererererererererererererererererererepossible)and it is bad luck for the bride to see both members of such a pair.Your job is to arrange people the table so as to avoid any bad luck.
Input
The input consists of a number of test cases、フォローアップby a line containing 0.Each test case gives n,the number of couples,followed by the number of adulterous pairs,followwed by the pairs,in the form“4 h 2 w”(husband from coup le 4,wife from coup 2),or「10 w 4 w」,or「3 h 1 berrow.」 n - 1 with the bride and groom being 0 w and 0 h.
Output
For each case,output a single line containing a list of the people that Shout be seated on the same side as the bride.If there are several solutions,any one will do.If there is solution,output a line containk.back。
Sample Input
10 6
3h 7h
5w 3w
7h 6w
8w 3w
7h 3w
2w 5h
0 0
Sample Output1h 2h 3w 4h 5h 6h 7h 8h 9h
ソurceWaterloo Local Contact,2007.9.29
件名:
新しいカップルが結婚して、招待されました。 n夫婦に結婚式に行きます。長いテーブルがあります。テーブルの両側にしか座ってはいけません。
以下の要求を満たす必要があります。
1.夫婦は同じ側に座ってはいけません。
2.n夫婦の中には姦通関係(男性、男女、女性を含む)があるかもしれません。姦通関係がある場合は、同時に花嫁の反対側に座ってはいけません。
可能なプログラムがあれば、花嫁と同じ側の人を出力します。
PS:
解を求める時は新郎と同じ側の人を選んで、出力する時は交換して新婦の同じ側の人です。iとjが奸情があるなら、iからj'まで、jからiまでの辺を加えて、新郎の辺に新婦を加えて、必ず新郎を選ぶと表しています。 この問題は花嫁を直接選ぶのは間違いやすいです。花嫁にも浮気があるかもしれないので、排除が必要です。
コードは以下の通りです
/*
1. (1h 2h , 1h->2w 2h->1w)
2.
3. ( , ; )
4. ( )
5.
6. ( , ( ) )
, , ,
*/
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
//2-SAT
const int MAXN = 1010;
const int MAXM = 100010;
struct Edge
{
int to;
int next;
} edge[MAXM];
int head[MAXN],tot;
void init()
{
tot = 0;
memset(head,-1,sizeof(head));
}
void addedge(int u,int v)
{
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++;
}
int Low[MAXN],DFN[MAXN],Stack[MAXN],Belong[MAXN];//Belong 1~scc
int Index,top;
int scc;
bool Instack[MAXN];
int num[MAXN];
void Tarjan(int u)//tarjan
{
int v;
Low[u] = DFN[u] = ++Index;
Stack[top++] = u;
Instack[u] = true;
for(int i = head[u]; i != -1; i = edge[i].next)
{
v = edge[i].to;
if( !DFN[v] )
{
Tarjan(v);
if(Low[u] > Low[v])Low[u] = Low[v];
}
else if(Instack[v] && Low[u] > DFN[v])
Low[u] = DFN[v];
}
if(Low[u] == DFN[u])
{
scc++;
do
{
v = Stack[--top];
Instack[v] = false;
Belong[v] = scc;
num[scc]++;
}
while(v != u);
}
}
//
bool solvable(int n)//n ,
{
memset(DFN,0,sizeof(DFN));
memset(Instack,false,sizeof(Instack));
memset(num,0,sizeof(num));
Index = scc = top = 0;
for(int i = 0; i < n; i++)
if(!DFN[i])
Tarjan(i);
for(int i = 0; i < n; i += 2)
{
if(Belong[i] == Belong[i^1])
return false;
}
return true;
}
//
queue<int>q1,q2;
vector<vector<int> > dag;// DAG
char color[MAXN];// , 'R'
int indeg[MAXN];//
int cf[MAXN];
void topsort(int n)
{
dag.assign(scc+1,vector<int>());
memset(indeg,0,sizeof(indeg));
memset(color,0,sizeof(color));
for(int u = 0; u < n; u++)//
for(int i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].to;
if(Belong[u] != Belong[v])
{
dag[Belong[v]].push_back(Belong[u]);
indeg[Belong[u]]++;
}
}
for(int i = 0; i < n; i += 2)
{
cf[Belong[i]] = Belong[i^1];
cf[Belong[i^1]] = Belong[i];
}
while(!q1.empty())q1.pop();
while(!q2.empty())q2.pop();
for(int i = 1; i <= scc; i++)
if(indeg[i] == 0)
q1.push(i);
while(!q1.empty())
{
int u = q1.front();
q1.pop();
if(color[u] == 0)
{
color[u] = 'R';
color[cf[u]] = 'B';
}
int sz = dag[u].size();
for(int i = 0; i < sz; i++)
{
indeg[dag[u][i]]--;
if(indeg[dag[u][i]] == 0)
q1.push(dag[u][i]);
}
}
}
int change(char s[])
{
int ret = 0;
int i = 0;
while(s[i]>='0' && s[i]<='9')
{
ret *= 10;
ret += s[i]-'0';
i++;
}
if(s[i] == 'w') //
return 2*ret;
else //
return 2*ret+1;
}
int main()
{
int n, m;
char s1[17], s2[17];
while(~scanf("%d%d",&n,&m))
{
if(n == 0 && m == 0)
break;
init();
while(m--)
{
scanf("%s%s",s1,s2);
int u = change(s1);
int v = change(s2);
addedge(u^1,v);// ,
addedge(v^1,u);
}
addedge(1,0);
if(solvable(2*n))//
{
topsort(2*n);
for(int i = 1; i < n; i++)
{
// color[Belong[
if(color[Belong[2*i]] == 'R')
printf("%dw",i);
else
printf("%dh",i);
if(i < n-1)
printf(" ");
else
printf("
");
}
}
else
printf("bad luck
");
}
return 0;
}