暑假第七周训练总结

因为我要缓考复习,所以这周看的算法内容比较少,这周看了2-sat问题和部分差分约束,顺带复习了一下之前的Tarjan算法,感觉太久没看又忘得差不多了,所以要勤加复习才行。

2-sat问题:

n个集合给出一些限制条件,要求满足限制条件,且限制条件往往是要求满足a就不能满足b,或者相反,故可以用强联通分量法(tarjan算法)来做(还有染色法)

2-sat模板:

洛谷p4782

#include<bits/stdc++.h>
using namespace std;
int n,m,t,p,q;
int i,a,j,b;
int dfn[2000010],low[2000010],belong[2000010];
bool f[2000010];
vector<int> v[2000010];
stack<int> s;
void tarjan(int x)//求出强联通分量的拓扑序反序
{
    int k;
    dfn[x]=low[x]=++t;
    f[x]=1;
    s.push(x);
    for(int i=0;i<v[x].size();i++)
    {
        k=v[x][i];
        if(!dfn[k])
        {
            tarjan(k);
            low[x]=min(low[x],low[k]);
        }
        else if(f[k])
        {
            low[x]=min(low[x],dfn[k]);
        }
    }
    if(dfn[x]==low[x])
    {
        p++;
        while(1)
        {
            q=s.top();
            s.pop();
            belong[q]=p;
            f[q]=0;
            if(q==x)
                break;
        }
    }
}
int main()
{
    cin>>n>>m;
//注意建图,详情看题解
    for(int y=1;y<=m;y++)
    {
        cin>>i>>a>>j>>b;
        if(a==1&&b==1)
        {
            v[i].push_back(j+n);
            v[j].push_back(i+n);
        }
        if(a==0&&b==0)
        {
            v[i+n].push_back(j);
            v[j+n].push_back(i);
        }
        if(a==1&&b==0)
        {
            v[i].push_back(j);
            v[j+n].push_back(i+n);
        }
        if(a==0&&b==1)
        {
            v[i+n].push_back(j+n);
            v[j].push_back(i);
        }
    }
    for(int i=1;i<=2*n;i++)
    {
        if(!dfn[i])
        {
            tarjan(i);
        }
    }
    for(int i=1;i<=n;i++)
    {
        if(belong[i]==belong[i+n])
        {
            cout<<"IMPOSSIBLE"<<endl;
            return 0;
        }
    }
    cout<<"POSSIBLE"<<endl;
    for(int i=1;i<=n;i++)
    {
        if(belong[i]>belong[i+n])
        {
            cout<<1<<' ';
        }
        else
        {
            cout<<0<<' ';
        }
    }
    return 0;
}

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值