居然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;
}

算是为假期开个好头吧