题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=1814
题解:
开始想用Tarjan缩点后拓扑排序搞定,后来怎么也不会输出最小字典序比较尴尬。。。最后还是学习了别人的暴力搜索2-SAT搞定了。。。
AC代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn = 16005;
struct node
{
int to, next;
}e[100000];
int head[maxn];
int ct;
void add(int s, int t)
{
e[ct].to = t;
e[ct].next = head[s];
head[s] = ct++;
}
int cnt;
int col[maxn];
int ans[maxn];
int n, m;
bool dfs(int u)
{
if (col[u] == 2)
return false;
if (col[u] == 1)
return true;
col[u] = 1;
col[u^1] = 2;
ans[cnt++] = u;
int i;
int k;
for (i=head[u]; i; i=e[i].next)
{
k = e[i].to;
if (!dfs(k))
return false;
}
return true;
}
bool solve()
{
int i, j;
memset(col,0,sizeof(col));
for (i=0; i<n; i++){
if (col[i])
continue;
cnt = 0;
if (!dfs(i))
{
for (j=0; j<cnt; j++)
{
col[ans[j]] = 0;
col[ans[j]^1] = 0;
}
if (!dfs(i^1))
return false;
}
}
return true;
}
int main()
{
while (~scanf("%d %d",&n, &m))
{
n <<= 1;
int i;
ct = 1;
memset(head,0,sizeof(head));
int a, b;
while (m--)
{
scanf("%d %d",&a, &b);
a--;
b--;
add(a, b^1);
add(b, a^1);//位运算异或操作
}
if (solve())
{
//for(int i = 0; i < n; i++)
// printf("%d %d\n", i, col[i]);
for (i=0; i<n; i++)
if(col[i] == 1)
printf("%d\n",i+1);
}
else
puts("NIE");
}
return 0;
}