题目描述
样例输入
3 2
1 3
2 4
样例输出
1
4
5
2
−
s
a
t
2-sat
2−sat
发现“
a
,
b
a,b
a,b互相厌恶”和“dang派在weiyuan会中恰有
1
1
1个代表”各自都不好转化成"若
A
A
A,则
B
B
B"的形式。
所以考虑结合两者:如果选了
a
a
a,则必须要选
b
b
b的dang派的另外一人。
同理如果选了
b
b
b,则必须要选
a
a
a的dang派的另外一人。
因为这里没有要求字典序最小(然而hdu1814上好像有)所以可以跑一个tarjan实现的2-sat.
中国gcd万岁!!!
代码
为什么像我这种自带大常数的选手加了快写之后就到了loj时间最快啊……有毒
#include<stdio.h>
#include<cstring>
#include<algorithm>
#include<math.h>
#include<vector>
#define re register int
#define rl register ll
using namespace std;
typedef long long ll;
int read() {
re x=0,f=1;
char ch=getchar();
while(ch<'0' || ch>'9') {
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0' && ch<='9') {
x=10*x+ch-'0';
ch=getchar();
}
return x*f;
}
inline void write(int x) {
if(x>9) write(x/10);
putchar(x%10+'0');
}
namespace I_Love {
const int Size=100005;
int n,m,cnt,a[Size],b[Size],head[Size];
struct Edge {
int v,next;
} w[Size<<1];
void AddEdge(int u,int v) {
w[++cnt].v=v;
w[cnt].next=head[u];
head[u]=cnt;
}
int tim,tot,top,stk[Size],dfn[Size],low[Size],belong[Size];
bool vis[Size];
inline int getid(int x) {
if(x&1) return x+1;
return x-1;
}
void Tarjan(int x) {
dfn[x]=low[x]=++tim;
stk[++top]=x;
vis[x]=true;
for(int i=head[x]; i; i=w[i].next) {
int nxt=w[i].v;
if(!dfn[nxt]) {
Tarjan(nxt);
low[x]=min(low[x],low[nxt]);
} else if(vis[nxt]) {
low[x]=min(low[x],dfn[nxt]);
}
}
if(low[x]==dfn[x]) {
int y;
tot++;
while(y=stk[top--]) {
belong[y]=tot;
vis[y]=false;
if(x==y) return;
}
}
}
void Fujibayashi_Ryou() {
n=read()<<1;
m=read();
for(re i=1; i<=m; i++) {
int u=read();
int v=read();
AddEdge(u,getid(v));
AddEdge(v,getid(u));
}
for(re i=1; i<=(n<<1); i++) {
if(!dfn[i]) {
Tarjan(i);
}
}
for(re i=1; i<=n; i+=2) {
if(belong[i]==belong[i+1]) {
printf("NIE");
return;
}
}
for(re i=1; i<=n; i+=2) {
if(belong[i]<belong[i+1]) {
write(i);
} else {
write(i+1);
}
putchar(10);
}
}
}
int main() {
I_Love::Fujibayashi_Ryou();
return 0;
}