您的位置:首页 > 其它

#1467 : 2-SAT·hihoCoder音乐节

2018-03-28 21:41 302 查看

描述

hihoCoder音乐节由hihoCoder赞助商大力主办,邀请了众多嘉宾和知名乐队参与演出。音乐会分为上午、下午两场进行,主办方指定了n首歌让乐队进行演唱。每首歌只会被演唱一次,要么在上午要么在下午。参加音乐会的嘉宾们对于歌曲的演唱时间有一些要求。具体来说,每位嘉宾会指定两首歌曲的演唱时间(上午或者下午)。如果最后实际的演出安排中,两首歌都没有达到嘉宾的要求,那么嘉宾就会对音乐节不滿意。如嘉宾A的要求是上午《我的滑板鞋》和下午《忐忑》,而最后的演出中上午没有《我的滑板鞋》只有《忐忑》,下午没有《忐忑》只有《我的滑板鞋》,那么嘉宾A是不满意的。音乐节主办方自然希望使所有嘉宾满意,但主办方后来发现有可能不存在一种歌曲的安排方案满足所有嘉宾,所以他们希望你判断一下这种情况是否会发生。解题方法提示

输入

输入第一行包含一个数字 K,代表K组数据。(K≤50)对于每一组数据,第一行包含两个非负整数n和m(n≤100,m≤1000),代表有n首歌和m位嘉宾。为了方便我们给予歌编号,编号分别从1 到n。接下的m行,每行都代表对应的嘉宾的喜好由一个英文字母(m或h)跟一个数字代表,如m1 代表这个评审喜欢第1首歌上午进行,而h2代表这个评审员喜欢第2首歌下午进行。

输出

对于每一组数据,输出一行,如果能满足所有嘉宾的情况,输出GOOD;否则输出BAD。样例输入
2
3 4
m3 h1
m1 m2
h1 h3
h3 m2
2 4
h1 m2
m2 m1
h1 h2
m1 h2
样例输出
GOOD
BAD

2-sat问题,好恶心,当时学习的时候没怎么做题。
做了好久。终于a了。
代码:#include<bits/stdc++.h>
using namespace std;
const int maxn=550+10;
int n,m;
int dfs_clock;
int scc_cnt;
vector<int> G[maxn];
int pre[maxn];
int low[maxn];
int sccno[maxn];
stack<int> S;
vector<int> F[maxn];
void dfs(int u)
{
pre[u]=low[u]=++dfs_clock;
S.push(u);
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i];
if(!pre[v])
{
dfs(v);
low[u]=min(low[u],low[v]);
}
else if(!sccno[v])
{
low[u]=min(low[u],pre[v]);
}
}
if(low[u] == pre[u])
{
scc_cnt++;
while(true)
{
int x=S.top(); S.pop();
sccno[x]=scc_cnt;
//F[scc_cnt].push_back(x);
if(x==u) break;
}
}
}

void find_scc()
{
scc_cnt=dfs_clock=0;
memset(sccno,0,sizeof(sccno));
memset(pre,0,sizeof(pre));
memset(low,0,sizeof(low));
for(int i=1;i<=2*n;i++)
{
if(!pre[i])dfs(i);
}
}
int q(char a[])
{
int l=strlen(a);
int sum=0;
for(int i=1;i<l;i++)
{
sum=sum*10+a[i]-'0';
}
//cout<<sum<<endl;
return sum;

}
/*
void add_clause(int x,int xval,int y,int yval)
{
x=x*2+xval;
y=y*2+yval;
G[x^1].push_back(y);
G[y^1].push_back(x);
}
*/
int main()
{
int t;
cin>>t;
while(t--)
{
scanf("%d%d",&n,&m);
for(int i=1;i<=2*n;i++) G[i].clear();
//for(int i=1;i<=2*n;i++) F[i].clear();
int u,v;
char s[6],x[6];
while(m--)
{
scanf("%s%s",s,x);
u=q(s);
v=q(x);
int un=u+n;
int vn=v+n;
if(s[0]=='h')swap(u,un);
if(x[0]=='h')swap(v,vn);
//cout<<u<<" "<<v<<endl;
G[vn].push_back(u);
G[un].push_back(v);
}
find_scc();

int sum=0;
/*
for(int i=1;i<=scc_cnt;i++)
{
for(int j=0;j<F[i].size();j++)
{
printf("%d ",F[i][j]);
}
printf("\n");
}
*/
for(int i=1;i<=n;i++)
{
if(sccno[i]==sccno[i+n])
{
sum=1;
}
}
if(sum)printf("BAD\n");
else printf("GOOD\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  2-sat 强连通分量