【bzoj 1823】滿漢全席

傳送門~

解題思路

每個菜品分爲滿式和漢式兩個點,若選了A點就必選B點則由A向B連邊。最後Tarjan縮點,若存在一個菜品的滿式和漢式在一個強連通分量中,則該方案不合法。
代碼:

#include<algorithm>
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<stack>
using namespace std;
stack <int> q;
int hed[205],nex[2005],lb[2005];
int low[205],dfn[205],block[205];
int Y,n,m,T,lo,tot;
inline int read(){
    int ret=0;
    char opt[10];
    scanf("%s",opt);
    int len=strlen(opt);
    for(int i=1;i<len;i++)
    ret=ret*10+opt[i]-'0';
    ret=ret<<1|(opt[0]=='h');
    return ret;
}
void add(int x,int y){
    lo++;
    nex[lo]=hed[x];
    hed[x]=lo;
    lb[lo]=y;
}
void dfs(int x){
    low[x]=dfn[x]=++T;q.push(x);
    for(int i=hed[x];i!=0;i=nex[i]){
        if(!dfn[lb[i]]){
            dfs(lb[i]);
            low[x]=min(low[x],low[lb[i]]);
        }
        else if(!block[lb[i]]) low[x]=min(low[x],dfn[lb[i]]);
    }
    if(low[x]==dfn[x]){
        tot++;
        int xx=0;
        while(xx!=x){
            xx=q.top();q.pop();
            block[xx]=tot;
        }
    }
}
void Tarjan(){
    for(int i=2;i<=n*2+1;i++) 
    if(!dfn[i]) dfs(i); 
    for(int i=2;i<=n*2+1;i++)
    if(block[i]==block[i^1]){
        printf("BAD\n");
        return ;
    }
    printf("GOOD\n");
}
int main(){
    scanf("%d",&Y);
while(Y--){ 
    memset(hed,0,sizeof(hed));
    memset(dfn,0,sizeof(dfn));
    memset(low,0,sizeof(low));
    memset(block,0,sizeof(block));
    T=lo=tot=0;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        int a=read(),b=read();  
        add(a^1,b);add(b^1,a);
    }
    Tarjan();           
}
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章