zoukankan      html  css  js  c++  java
  • 2-SAT模板

    n-SAT 是给定多个条件,问是否有一个赋值方式使所有条件得到满足。

    每个条件都有n个变量, 而2-SAT 是存在时间复杂度为(O(nm)或O(n+m))的做法((m)是条件数)的算法的问题。

    2-SAT往往是判断是否有方案使条件得到满足的一个算法。

    建图:
    求解2-SAT问题,需要转移到图上,对于每个变量都定义两个点分别表示true和false,用点a到点b连边表示a要选b也一要选。因此a的拓扑序一定比b要大,因为b给了a一个限制。

    判断:

    2-SAT有多种实现方式,用的最多的就是用tarjan来判断可行性。

    tarjan来判断可行性的原理是,通过缩点之后,如果每个变量的true和false不属于一个连通分量,就说明可行。

    输出方案:

    因为缩点之后是深搜使得tarjan缩完点之后的编号是是倒着的拓扑序,而我们又想找到对后来限制少的点,即拓扑序大的点,所以我们找tarjan缩完点之后的编号小的点。

    #include <bits/stdc++.h>
    #include <stack>
    #define N 2001010
    using namespace std;
    struct edge {
    	int to, nex;
    }e[N * 2];
    int n, m, tot, color, cnt, flag[N], lin[N], dfn[N], low[N], belong[N], vis[N];
    stack <int> s;
    inline void add(int f, int t)
    {
    	e[++cnt].to = t;
    	e[cnt].nex = lin[f];
    	lin[f] = cnt;
    }
    void tarjan(int now)
    {
     	dfn[now] = low[now] = ++tot;
     	vis[now] = 1, s.push(now);
     	for (int i = lin[now]; i; i = e[i].nex)
     	{
     		int to = e[i].to;
     		if (!dfn[to])
     			tarjan(to), low[now] = min(low[now], low[to]);
     		else if (vis[to])
     			low[now] = min(low[now], dfn[to]);
     	}
     	if (dfn[now] == low[now])
     	{
     		++color;
     		while (!s.empty())
     		{
     			int v = s.top(); s.pop();
     			belong[v] = color, vis[v] = 0;
     			if (v == now) break;
     		}
     	}
    }
    int main()
    {
     	scanf("%d%d", &n, &m);
     	while (m--)
     	{
     		int i, a, j, b;		
     		scanf("%d%d%d%d", &i, &a, &j, &b);
     		add(j + (b ^ 1) * n, i + a * n);
      		add(i + (a ^ 1) * n, j + b * n);
     	}//就是xi为a时, xj一定 不为b,反过来xj一定不为b时,xi并不满足一定为a,因此要从j+(b^1)*n连向i+a*n 
      	for (int i = 1; i <= n * 2; i++)
      		if (!dfn[i])     	
     		 	tarjan(i);   	
      	for (int i = 1; i <= n; i++)
     		if (belong[i] == belong[i + n])	
     			printf("IMPOSSIBLE
    "), exit(0);
     	printf("POSSIBLE
    ");	//最后我们要选对后来限制小的点,所以就是要选拓扑序大的,也就是belong小的 
     	for (int i = 1; i <= n; i++)
     	{						
     		if (belong[i] < belong[i + n])//无相等情况 
     			printf("1 ");	
     		else				
     			printf("0 ");	
     	}						
     	return 0;				
    }
    
  • 相关阅读:
    MySQL——MySQL用户与数据库的关系
    Kafka——Kakfa的设计思想
    Hibernate建表——将MySQL的JSON列映射到Java字段(Jpa/Hibernate——Java)
    Spring Boot——Apache Commons包作用说明
    word转html工具
    html导出word
    html导出pdf
    获取dubbo-admin.war(自己maven编译)
    ajax提交表单中文呈现乱码解决
    JVM优化
  • 原文地址:https://www.cnblogs.com/liuwenyao/p/11640411.html
Copyright © 2011-2022 走看看