您的位置:首页 > Web前端 > JavaScript

【bzoj1823】[JSOI2010]满汉全席 2-SAT

2017-02-22 13:41 260 查看
第一次写2-SAT,总结起来这个东西就是找到一些条件使得a成立b一定成立,这样的话如果a成立并且a’也成立,a’成立a也成立即这两个点在同一个强连通分量中,那么无解,反之就一定可以构造出一组解,所以这道题我们只要将两个条件必须满足其一转化为a’->b,b’->a然后跑一边tarjan就好了。

#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<iostream>
#include<iomanip>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
struct bian
{
int l,r;
}a[10000];
int fir[1000];
int nex[10000];
int tot=1;
void add_edge(int l,int r)
{
a[++tot].l=l;
a[tot].r=r;
nex[tot]=fir[l];
fir[l]=tot;
}
int pre[1000];
int low[1000];
int sceno[1000];
int dfs_clock;
int my_stack[10000];
int top=0;
int scc_sum;
void dfs(int u)
{
pre[u]=low[u]=++dfs_clock;
my_stack[++top]=u;
for(int o=fir[u];o;o=nex[o])
{
if(!pre[a[o].r])
{
dfs(a[o].r);
low[u]=min(low[u],low[a[o].r]);
}
else if(!sceno[a[o].r]) low[u]=min(low[u],pre[a[o].r]);
}
if(low[u]==pre[u])
{
scc_sum++;
int yuan=top;
while(1)
{
int t=my_stack[top];
top--;
sceno[t]=scc_sum;
if(t==u) break;
}
}
}
char s1[10],s2[10];
int main()
{
int T;
scanf("%d",&T);
for(int hh=1;hh<=T;hh++)
{
memset(fir,0,sizeof(fir));
memset(pre,0,sizeof(pre));
memset(sceno,0,sizeof(sceno));
memset(low,0,sizeof(low));
dfs_clock=scc_sum=top=0;
tot=1;
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
scanf("%s%s",s1,s2);
int z1= (s1[0]=='h')?0:1;
int z2= (s2[0]=='h')?0:1;
int l=0;
int wz=1;
while(s1[wz]>='0' && s1[wz]<='9') l=l*10+s1[wz]-'0',wz++;
int r=0;
wz=1;
while(s2[wz]>='0' && s2[wz]<='9') r=r*10+s2[wz]-'0',wz++;
l=l*2+z1;
r=r*2+z2;
add_edge(l^1,r);
add_edge(r^1,l);
}
int sum=0;
for(int i=2;i<=2*n+1;i++)
if(!pre[i])
dfs(i);
bool flag=true;
for(int i=1;i<=n;i++)
{
if(sceno[i*2]==sceno[i*2+1])
{
flag=false;
break;
}
}
if(flag) cout<<"GOOD"<<endl;
else cout<<"BAD"<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: