2-sat模板- 输出可行解

自己写的代码

using namespace std;
const int maxn = 1e6;
int head[maxn];
int DFN[maxn],LOW[maxn],stk[maxn],visit[maxn],belong[maxn];
vector<int> scc[maxn];
int tot,idx,cnt,sccnum;
int n,color[maxn],degree[maxn],pos[maxn];
struct Es{ 
    int v; 
    int next; 
    int cost; 
}Es[maxn<<1];  
vector<int> bkG[maxn];
void init(){ 
    sccnum = tot = idx = cnt = 0; 
    memset(head,-1,sizeof(head)); 
    memset(DFN,0,sizeof(DFN)); 
    memset(LOW,0,sizeof(LOW)); 
    memset(visit,0,sizeof(visit)); 
	memset(color,0,sizeof(color)); 
	memset(degree,0,sizeof(degree));
	memset(pos,0,sizeof(pos));
    for(int i = 0;i < maxn;i++) scc[i].clear();
    for(int i = 0;i < maxn;++i) bkG[i].clear();
}
inline void add_edge(int i,int j,int cost = 1){   
    Es[cnt].v = j; 
    Es[cnt].cost = cost; 
    Es[cnt].next = head[i]; 
    head[i] = cnt++; 
}   
void tarjan(int x)
{
     DFN[x]=LOW[x]=++tot;
     stk[++idx]=x;
     visit[x]=1;
     for(int i=head[x];i!=-1;i=Es[i].next)
     {
         if(!DFN[Es[i].v]) {
             tarjan(Es[i].v);
             LOW[x] = min(LOW[x],LOW[Es[i].v]);
         }
         else if(visit[Es[i].v ]){  
             LOW[x] = min(LOW[x],DFN[Es[i].v]);
         }
     }
     if(LOW[x]==DFN[x])
     {
     	 ++sccnum;
         do{
             int item = stk[idx];
             belong[item] = sccnum;
             scc[sccnum].push_back(item);
             visit[item]=0;
             idx--;
         }while(x!=stk[idx+1]);
     }
     return ;
}
bool check(){
	for(int i = 1;i <= n;i++){
		if(belong[i] == belong[i+n]) return false;
	}
	return true;
}
bool solve(){
	for(int i = 1;i <= 2*n;++i )
		if(!DFN[i]) 
			tarjan(i);
	if(!check()) return false;
	for(int i = 1;i <= n;++i){
		if(!pos[belong[i]]){
			pos[belong[i]] = belong[i+n];
			pos[belong[i+n]] = belong[i];
		}
	}
	
	for(int i = 1;i <= 2*n;++i){
		for(int e = head[i];e != -1;e = Es[e].next){
			int v = Es[e].v;
			if(belong[i] != belong[v]){
				degree[belong[i]]++;
				bkG[belong[v]].push_back(belong[i]);
			}
		}
	}
	queue<int> que;
	for(int i = 1;i <= sccnum;++i){
		if(!degree[i])
			que.push(i);
	}
	
	while(!que.empty()){
		int u = que.front();
		que.pop();
		
		if(!color[u]){
			color[u] = 1;color[pos[u]] = 2;
		}
		
		for(int i = 0;i < bkG[u].size();++i){
			int v = bkG[u][i];
			degree[v]--;
			if(!degree[v])
				que.push(v);
		}
	}
	
	//在这里准备输出答案
	//为1表示选中,为2表示为选中
	/*
	for(int i = 1;i <= n;++i){
		if(color[belong[i]] == 1) {
			//Yes
		}
		else{
			//No
		}
	} 
	*/
	return true;
}

//使用方法

1.init()

2.用add_edge建图

3.用solve()函数求解



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值