【2-SAT(最小字典序/暴力染色)】HDU1814-Peaceful Commission

【题目大意】

和平委员会每个党派有2个人,只能派出其中1个,其中有一些人之间互相讨厌不能同时派出。求出派遣方案,如果有多种方案输出字典序最小的方案。

【思路】

最小字典序只能用暴力染色。初始时均没有染色。枚举将党派第一个人染成红色,然后dfs把和它相连的全部染成红色,如果其中有的是蓝色那么矛盾;如果第一种情况矛盾那么dfs第二个人染成红色,如果也矛盾说明无解。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<vector>
 6 #define W 0
 7 #define R 1
 8 #define B 2
 9 using namespace std;
10 const int MAXN=(8000+50)*2;
11 int n,m;
12 vector<int> E[MAXN];
13 int col[MAXN],ans[MAXN],cnt;
14 
15 void addedge(int u,int v)
16 {
17     E[u].push_back(v);
18 }
19 
20 int dfs(int u)
21 {
22     col[u]=R;
23     col[u^1]=B;
24     ans[++cnt]=u;
25     for (int i=0;i<E[u].size();i++)
26     {
27         int v=E[u][i];
28         if (col[v]==R) continue;
29         if (col[v]==B || !dfs(v)) return 0;
30     }
31     return 1;
32 }
33 
34 void init()
35 {
36     for (int i=0;i<m;i++)
37     {
38         int u,v;
39         scanf("%d%d",&u,&v);
40         u--;v--;
41         addedge(u,v^1);
42         addedge(v,u^1);
43     }
44 }
45 
46 int solve()
47 {
48     memset(col,0,sizeof(col));
49     for (int i=0;i<n*2;i++)
50         if (!col[i])
51         {
52             cnt=0;
53             if (!dfs(i))
54             {
55                 for (int j=1;j<=cnt;j++) col[ans[j]]=col[ans[j]^1]=W;
56                 if (!dfs(i^1)) return 0;
57             }
58         }
59     return 1;
60 }
61 
62 int main()
63 {
64     //freopen("spo0.in","r",stdin);
65     //freopen("spo0.out","w",stdout); 
66     while (scanf("%d%d",&n,&m)!=EOF)
67     {
68         for (int i=0;i<2*n;i++) vector<int>().swap(E[i]);//不要忘记清空vector 
69         init();
70         if(solve())
71         {
72             for(int i=0;i<2*n;i++)
73             {
74                 if(col[i]==R) printf("%d\n", i+1);
75             }
76         }
77         else
78         {
79             printf("NIE\n");
80         }
81     }
82     return 0;
83 }

 

转载于:https://www.cnblogs.com/iiyiyi/p/5710631.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值