P4171 [JSOI2010] 满汉全席 2-SAT
P4171 [JSOI2010] 满汉全席 2-SAT
思路:
2-SAT模板题,我们将满席定为1,汉席定为0.那么建边即可。判断同一道菜满汉是否在强联通分量中即可。
注意多测清空!!!
代码:
vector<int> e[N];
stack<int> stk;
int dfn[N],low[N],tot;
int instk[N],scc[N],siz[N],cnt;
int n,m;
void tarjan(int u){
dfn[u]=low[u]=++tot;
stk.push(u);instk[u]=1;
for(auto v:e[u]){
if(!dfn[v]){
tarjan(v);
low[u]=min(low[u],low[v]);
}else if(instk[v]) low[u]=min(low[u],dfn[v]);
}
if(dfn[u]==low[u]){
int v;++cnt;
do{
v=stk.top();
stk.pop();
instk[v]=0;
scc[v]=cnt;
siz[cnt]++;
}while(v!=u);
}
}
void init(){
tot=0,cnt=0;
for(int i=0;i<2*n;i++){
e[i].clear();
instk[i]=0;
dfn[i]=low[i]=0;
}
for(int i=1;i<=cnt;i++){
siz[i]=0;
scc[i]=0;
}
}
void Showball(){
cin>>n>>m;
init();
while(m--){
char x,y;
int u,v;
cin>>x>>u>>y>>v;
u--;v--;
e[(u<<1)+!(x=='m')].pb((v<<1)+(y=='m'));
e[(v<<1)+!(y=='m')].pb((u<<1)+(x=='m'));
}
for(int i=0;i<2*n;i++){
if(!dfn[i]) tarjan(i);
}
for(int i=0;i<n;i++){
if(scc[i<<1]==scc[i<<1|1]) return cout<<"BAD\n",void();
}
cout<<"GOOD\n";
}