光明正大 @ 2020-05-20 20:42:08
RT
WA on #1 #2 #3 #6 #9
求大佬帮忙查错
//2-SAT:汉菜1~n,满菜n+1~2*n
//注意清空!!!
#include<bits/stdc++.h>
using namespace std;
const int maxn=110,maxm=2e3+10;
int T,n,m,idx,cnt,head[maxn<<1],dfn[maxn<<1],low[maxn<<1],ty[150];//把h,m映射为1~n,n+1~2*n
struct Edge{int to,next;} e[maxm<<1];
inline void add(int u,int to) {e[++cnt].to=to;e[cnt].next=head[u];head[u]=cnt;}
int tot,id[maxn<<1];
stack<int> s;
bool ok,ins[maxn<<1];
inline void tarjan(int u) {
dfn[u]=low[u]=++idx;s.push(u);ins[u]=1;
for(int i=head[u];i;i=e[i].next) {
int v=e[i].to;
if(!dfn[v]) tarjan(v),low[u]=min(low[u],low[v]);
else if(ins[v]) low[u]=min(low[u],dfn[v]);
}
if(low[u]==dfn[u]) {
tot++;
while(s.top()!=u) {id[s.top()]=tot;ins[s.top()]=0;s.pop();}
id[s.top()]=tot;ins[s.top()]=0;s.pop();
}
}
inline int gint() {//拙劣的非负快读(据说还有更快的)。
int ff=1,ee=0;char ss=getchar();
while(ss<'0'||ss>'9') ss=getchar();
while(ss>='0'&&ss<='9') {ee=(ee<<1)+(ee<<3)+(ss^48);ss=getchar();}
return ee*ff;
}
char c1[10],c2[10];
int main() {
T=gint();ty['h']=0;ty['m']=1;
while(T--) {
n=gint();m=gint();ok=1;
memset(id,0,sizeof id);
memset(low,0,sizeof low);
memset(dfn,0,sizeof dfn);
memset(head,0,sizeof head);cnt=idx=tot=0;
for(int i=1,x,y,l1,l2;i<=m;i++) {
scanf("%s%s",c1,c2);x=y=0;
l1=strlen(c1);l2=strlen(c2);
for(int j=1;j<l1;j++) x=(x<<3)+(x<<1)+(c1[j]^48);
for(int j=1;j<l2;j++) y=(y<<3)+(y<<1)+(c2[j]^48);
add(x+(ty[(int)c1[0]]^1)*n,y+ty[(int)c2[0]]*n);
add(y+(ty[(int)c2[0]]^1)*n,x+ty[(int)c1[0]]*n);
}
for(int i=1;i<=(n<<1);i++) if(!dfn[i]) tarjan(i);
for(int i=1;i<=(n<<1);i+=2) if(id[i]==id[i+1]) {puts("BAD");ok=0;break;}
if(ok) puts("GOOD");
}
return 0;
}
by metaphysis @ 2020-05-21 09:09:17
此题是典型的2-SAT,对于此类问题来说,解题的关键是建立有向图中的边,而缩点是模板操作,基本上不会(也不应)出什么错。您能解释下您建边的逻辑吗?
我的博客有一篇关于2-SAT的文章,希望对您有所帮助:布尔适定性问题(2-SAT)。
@光明正大
by 光明正大 @ 2020-05-22 12:56:44
@metaphysis
我将汉菜标记为1~n,满菜标记为n+1~2*n,对于一位评委,若一样菜没有按照他想要的方式做,那么另一道菜一定要按照他想要的方式做,以此连边。
我的ty[]是将h,m映射为0,1的
我找到错误了,判断时应该为id[i],id[i+n]我手误打成了id[i],id[i+1],不过还是谢谢您。
by metaphysis @ 2020-05-22 15:18:51
祝贺您此题获得通过!
@光明正大