hiho一下 第一百三十四周 #1468 : 2-SAT·hihoCoder新春晚会 【2-SAT 之 枚举--搜索】

#1468 : 2-SAT·hihoCoder新春晚会

时间限制: 10000ms
单点时限: 1000ms
内存限制: 256MB
描述

hihoCoder新春晚会正在紧张地筹备中。晚会分为上半场和下半场,总导演小Hi现在要为N个节目安排演出时间(上半场或下半场)。为了描述方便,我们将第i个节目对应两个编号2i-1和2i,分别表示把第i个节目安排在上半场和下半场。

由于演员、道具和布景的限制。有些安排之间存在冲突,比如编号1的安排和编号4的安排有冲突,意味着"把第1个节目安排在上半场"同"把第2个节目安排在下半场"有冲突。

现在小Hi手里有M对编号,表示冲突的节目安排。他的任务是帮助主办方安排出节目演出的合理时间。

解题方法提示

输入

第一行包含两个非负整数n和m(n≤8000,m≤20000),代表有n个节目和m对冲突。

接下来m行每行两个数x和y,表示编号x和编号y冲突。

输出

输出n行,每行一个数,从小到大输出最后进行演出的编号。若有多解,则输出字典序最小的。无解则输出NIE。

样例输入
3 2
1 3
2 4
样例输出
1
4
5

枚举每个点,然后通过正向边和反向边判断是否成立。


开始准备用强连通来写,无法得到最小字典序---然后GG-.-



有此情况:A  --》 B       A  --》 B’      B --》 A’       B‘ --》A’

则下面代码错误-.-

附错误代码:

#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
bool fafe[16100],da[16100];
int cmp[16100];
vector<int> V[16100],FV[16100],G,K[16100];
int ff(int b)
{
    if ((b|1)==b) b++;
    else b--;
    return b;
}
void add_edge(int a,int b)
{
    b=ff(b);
    V[a].push_back(b);
    FV[b].push_back(a);
}
void dfs(int x)
{
    fafe[x]=true;
    int v;
    for (int i=0;i<V[x].size();i++)
    {
        v=V[x][i];
        if (!fafe[v]) dfs(v);
    }
    G.push_back(x);
}
void fdfs(int x,int y)
{
    K[y].push_back(x);
    fafe[x]=true;
    cmp[x]=y;
   // printf("%d--------%d\n",x,y);
    for (int i=0;i<FV[x].size();i++)
    {
        int v=FV[x][i];
        if (!fafe[v]) fdfs(v,y);
    }
}
int main()
{
    int n,m,a,b;
    scanf("%d%d",&n,&m);
    while (m--)
    {
        scanf("%d%d",&a,&b);
        add_edge(a,b);
        add_edge(b,a);
    }
    memset(fafe,false,sizeof(fafe));
    for (int i=1;i<=n*2;i++)
    {
        if (!fafe[i]) dfs(i);
    }
    memset(fafe,false,sizeof(fafe));
    for (int i=G.size()-1;i>=0;i--)
    {
        if (!fafe[G[i]]) fdfs(G[i],i);
    }
    bool ans=false;
    for (int i=1;i<2*n;i+=2)
    {
        if (cmp[i]==cmp[i+1])
        {
            ans=true;
            break;
        }
    }
    if (ans)
    {
        printf("NIE\n");
    }
    else
    {
        memset(da,false,sizeof(da));
        memset(fafe,false,sizeof(fafe));/*
        for (int i=1;i<=2*n;i++)
            printf("%d %c",cmp[i],i==2*n?'\n':' ');*/
        for (int i=1;i<=2*n;i++)
        {
            if (!fafe[i])
            {
                int hao=cmp[i],v;
                for (int j=0;j<K[hao].size();j++)
                {
                    v=K[hao][j];
                    da[v]=true;
                    fafe[v]=fafe[ff(v)]=true;
                }
            }
        }
        for (int i=1;i<=2*n;i++)
        {
            if (da[i])
                printf("%d\n",i);
        }
    }
    return 0;
}




所以就是    强连通判可行性,枚举搜索求解-.-(强连通部分可以去掉,直接在枚举时可判断有无解)。

代码:

#include<cstdio>
#include<vector>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
bool fafe[261000];
int da[261000];
int cmp[261000];
vector<int> V[261000],FV[261000],G,K[261000],Q,W;
queue<int> que1,que2;
int ff(int b)
{
    if ((b|1)==b) b++;
    else b--;
    return b;
}
void add_edge(int a,int b)
{
    b=ff(b);
    V[a].push_back(b);
    FV[b].push_back(a);
}
void dfs(int x)
{
    fafe[x]=true;
    int v;
    for (int i=0;i<V[x].size();i++)
    {
        v=V[x][i];
        if (!fafe[v]) dfs(v);
    }
    G.push_back(x);
}
void fdfs(int x,int y)
{
    K[y].push_back(x);
    fafe[x]=true;
    cmp[x]=y;
    for (int i=0;i<FV[x].size();i++)
    {
        int v=FV[x][i];
        if (!fafe[v]) fdfs(v,y);
    }
}
int main()
{
    int n,m,a,b;
    scanf("%d%d",&n,&m);
    while (m--)
    {
        scanf("%d%d",&a,&b);
        add_edge(a,b);
        add_edge(b,a);
    }
    memset(fafe,false,sizeof(fafe));
    for (int i=1;i<=n*2;i++)
    {
        if (!fafe[i]) dfs(i);
    }
    memset(fafe,false,sizeof(fafe));
    for (int i=G.size()-1;i>=0;i--)
    {
        if (!fafe[G[i]]) fdfs(G[i],i);
    }
    bool ans=false;
    for (int i=1;i<2*n;i+=2)
    {
        if (cmp[i]==cmp[i+1])
        {
            ans=true;
            break;
        }
    }
    if (ans)
    {
        printf("NIE\n");
    }
    else
    {
        memset(da,0,sizeof(da));
        memset(fafe,false,sizeof(fafe));
        for (int i=1;i<=2*n;i++)
        {
            if (da[i]==0)
            {
                while (!que1.empty())
                    que1.pop();
                while (!que2.empty())
                    que2.pop();
                Q.clear();
                W.clear();
                que1.push(i);
                que2.push(ff(i));
                Q.push_back(i);
                W.push_back(ff(i));
                da[i]=1;
                da[ff(i)]=2;
                bool fa=true;
                int v;
                while (!que1.empty())
                {
                    a=que1.front();
                    que1.pop();
                    for (int j=0;j<V[a].size();j++)
                    {
                        v=V[a][j];
                        if (da[v]==0)
                        {
                            que1.push(v);
                            que2.push(ff(v));
                            Q.push_back(v);
                            W.push_back(ff(v));
                            da[v]=1;
                            da[ff(v)]=2;
                        }
                        else if (da[v]==2)
                        {
                            fa=false;
                            break;
                        }
                    }
                    if (!fa) break;
                    while (!que2.empty())
                    {
                        a=que2.front();
                        que2.pop();
                        for (int j=0;j<FV[a].size();j++)
                        {
                            v=FV[a][j];
                            if (da[v]==0)
                            {
                                que2.push(v);
                                que1.push(ff(v));
                                W.push_back(v);
                                Q.push_back(ff(v));
                                da[v]=2;
                                da[ff(v)]=1;
                            }
                            else if (da[v]==1)
                            {
                                fa=false;
                                break;
                            }
                        }
                        if (!fa) break;
                    }
                    if (!fa) break;
                }
                if (!fa)
                {
                    for (int i=0;i<Q.size();i++)
                        da[Q[i]]=0;
                    for (int i=0;i<W.size();i++)
                        da[W[i]]=0;
                }
            }
        }
        for (int i=1;i<=2*n;i++)
        {
            if (da[i]==1)
                printf("%d\n",i);
        }
    }
    return 0;
}






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值