hdu1814Peaceful Commission2-SAT输出最小解

Posted MissZhou要努力

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu1814Peaceful Commission2-SAT输出最小解相关的知识,希望对你有一定的参考价值。

居然1A了!!之前没调对居然只是多乘2了 (⊙﹏⊙)b 而且加边写反了==

题解:每个党派需要在两个代表中选一个,这2*n个代表中有彼此讨厌的m对人,输出n个去开会的代表

重点不在于怎么建边(建边这么so easy的事居然脑袋短路也是醉了==)在于怎么输出,网上的方法真的好麻烦,为什么非得染三个颜色的点啊我就不懂了,可能是模板的思路不好造成的吧

刘汝佳的书上说这个模板的思路是:逐一考虑没有赋值的变量(0~n-1范围内)即真、假未知的点,先假设这个变量是假(这个正好和题中要求一致,要是输出最大值就得先染色为真的结点了),然后顺着有向边标记所有能标记的点,如果发现对应为真的点被标记,那么“为假”的假定不成立,需要改成“为真”,然后重新标记。注意,这个算法没有回溯过程!。所以,当要重新标记时,之前那个点没有从0改成1.如果输出的“假”时候,需要保证“假”=1,“真”=0;其他情况 输出“真”

=============================分割线========================================

经测试,

for(int i=0;i<n;i++)  
              
                if(solver.mark[i<<1]) printf("%d\\n",i<<1|1);  
                else printf("%d\\n",(i<<1)+2);  
              
答案也对,其实我还是觉得是数据不严谨导致的,虽然poj3648也是只判断==1不用对点==0,因为算法没有回溯过程,只是判断一个点并不能保证这个点是真正的“真”


/***********
hdu1814
2016.1.15
998MS 2924K 1784 B G++
***********/
#include <iostream>
#include<cstring>
#include<cstdio>
#include<vector>
using namespace std;
#define maxn 8004
struct TWOSAT

    int n;
    vector<int>G[maxn*2];
    bool mark[maxn*2];
    int S[maxn*2],c;
    bool dfs(int x)
    
        if(mark[x^1])return false;
        if(mark[x]) return true;
        mark[x]=true;
        S[c++]=x;
        for(int i=0;i<G[x].size();i++)
            if(!dfs(G[x][i])) return false;
        return true;
    
    void init(int n)
    
        this->n=n;
        for(int i=0;i<n*2;i++) G[i].clear();
        memset(mark,0,sizeof(mark));
    
    void add_clause(int x,int y)
    
        G[x].push_back(y^1);
        G[y].push_back(x^1);///不一定是+1、-1!!而且本身就2n不用乘以2
    
    bool solve()
    
        for(int i=0;i<2*n;i+=2)
        
            if(!mark[i]&&!mark[i+1])
            
                c=0;
                if(!dfs(i))
                
                    while(c>0) mark[S[--c]]=false;
                    if(!dfs(i+1)) return false;
                
            
        
        return true;
    
solver;
int n,m;

int main()

   // freopen("cin.txt","r",stdin);
    while(~scanf("%d%d",&n,&m))
    
        solver.init(n);
        for(int i=0;i<m;i++)
        
            int a,b;
            scanf("%d%d",&a,&b);
            a--;b--;
            solver.add_clause(a,b);
        
        if(!solver.solve()) puts("NIE");
        else
        
            for(int i=0;i<n;i++)
            
                if(solver.mark[i<<1]&!solver.mark[i<<1|1]) printf("%d\\n",i<<1|1);
                else printf("%d\\n",(i<<1)+2);
            
        
    
    return 0;


算是为假期开个好头吧

以上是关于hdu1814Peaceful Commission2-SAT输出最小解的主要内容,如果未能解决你的问题,请参考以下文章

HDU1814 Peaceful Commission 2-sat

HDU 1814 Peaceful Commission(2-sat 模板题输出最小字典序解决方式)

hdu1814Peaceful Commission2-SAT输出最小解

hdu1814Peaceful Commission2-SAT输出最小解

HDOJ 1814 Peaceful Commission

「HDU」5434 Peaceful Small Elephant