HDU 3062 Party(2-SAT模版题)

摘要:
有n对夫妇被邀请参加聚会。由于场地问题,只有一对夫妇可以参加。在这20万人中,有些人之间有很大的矛盾。两个矛盾的人不会同时出现在聚会上。),(好。用C将第二个代码更改为312MS++
Problem Description
有n对夫妻被邀请参加一个聚会,因为场地的问题,每对夫妻中只有1人可以列席。在2n 个人中,某些人之间有着很大的矛盾(当然夫妻之间是没有矛盾的),有矛盾的2个人是不会同时出现在聚会上的。有没有可能会有n 个人同时列席?
Input
n: 表示有n对夫妻被邀请 (n<= 1000)
m: 表示有m 对矛盾关系 ( m < (n - 1) * (n -1))
在接下来的m行中,每行会有4个数字,分别是 A1,A2,C1,C2
A1,A2分别表示是夫妻的编号
C1,C2 表示是妻子还是丈夫 ,0表示妻子 ,1是丈夫
夫妻编号从 0 到 n -1
Output
如果存在一种情况 则输出YES
否则输出 NO
思路:2-SAT模版题,分别要求夫妻必上一个、仇人不能同时上
两个代码,第一个是普通的搜索,第二个是tarjan的解法,第一个593MS,第二个625MS(难道写挫了。。。?),(好吧用改一下第二个代码用C++交变成了312MS……)
HDU 3062 Party(2-SAT模版题)第1张HDU 3062 Party(2-SAT模版题)第2张
1 #include <cstdio>
2 #include <cstring>
3 using namespacestd;
4 
5 const int MAXN = 4010;
6 const int MAXM = 1010*1010*3;
7 
8 structTwoSAT{
9     intn, ecnt;
10     boolmark[MAXN];
11     int St[MAXN], c;//手动栈
12     inthead[MAXN];
13     intnext[MAXM], to[MAXM];
14 
15     bool dfs(intx){
16         if(mark[x^1]) return false;
17         if(mark[x]) return true;
18         mark[x] = true;
19         St[c++] =x;
20         for(int p = head[x]; p; p =next[p])
21             if(!dfs(to[p])) return false;
22         return true;
23 }
24 
25     void init(intn){
26         this->n =n;
27         ecnt = 2;
28         memset(head,0,sizeof(head));
29         memset(mark,0,sizeof(mark));
30 }
31 
32     void addEdge1(int x, int y){//x*y=false
33         to[ecnt] = y^1; next[ecnt] = head[x]; head[x] = ecnt++;
34         to[ecnt] = x^1; next[ecnt] = head[y]; head[y] = ecnt++;
35 }
36 
37     void addEdge2(int x, int y){//x+y=true
38         to[ecnt] = y; next[ecnt] = head[x^1]; head[x^1] = ecnt++;
39         to[ecnt] = x; next[ecnt] = head[y^1]; head[y^1] = ecnt++;
40 }
41 
42     boolsolve(){
43         for(int i = 0; i < n*2; i += 2)
44             if(!mark[i] && !mark[i+1]){
45                 c = 0;
46                 if(!dfs(i)) {
47                     while(c>0) mark[St[--c]] = false;
48                     if(!dfs(i^1)) return false;
49 }
50 }
51         return true;
52 }
53 } G;
54 
55 intmain(){
56     intn, m, a, b, c, d;
57     while(scanf("%d%d",&n,&m)!=EOF){
58 G.init(n);
59         for(int i = 0; i < n; ++i) G.addEdge2(i*2,(i+n)*2);
60         while(m--){
61             scanf("%d%d%d%d",&a,&b,&c,&d);
62             G.addEdge1((a + n*c)*2, (b + n*d)*2);
63 }
64         if(G.solve()) printf("YES
");
65         else printf("NO
");
66 }
67     return 0;
68 }
View Code
HDU 3062 Party(2-SAT模版题)第3张HDU 3062 Party(2-SAT模版题)第4张
1 #include <cstdio>
2 #include <cstring>
3 using namespacestd;
4 
5 const int MAXN = 2010;
6 const int MAXM = 1010*1010*2;
7 
8 structTwoSAT{
9     intn, ecnt, dfs_clock, scc_cnt;
10     int St[MAXN], c;//手动栈
11     inthead[MAXN], lowlink[MAXN], pre[MAXN], sccno[MAXN];
12     intnext[MAXM], to[MAXM];
13 
14     void dfs(intu){
15         pre[u] = lowlink[u] = ++dfs_clock;
16         St[++c] =u;
17         for(int p = head[u]; p; p =next[p]){
18             int &v =to[p];
19             if(!pre[v]){
20 dfs(v);
21                 if(lowlink[u] > lowlink[v]) lowlink[u] =lowlink[v];
22             }else if(!sccno[v]){
23                 if(lowlink[u] > pre[v]) lowlink[u] =pre[v];
24 }
25 }
26         if(lowlink[u] ==pre[u]){
27             scc_cnt++;
28             while(true){
29                 int x = St[c--];
30                 sccno[x] =scc_cnt;
31                 if(x == u) break;
32 }
33 }
34 }
35 
36     void init(intn){
37         this->n =n;
38         ecnt = 2; dfs_clock = scc_cnt = 0;
39         memset(head,0,sizeof(head));
40         memset(sccno,0,sizeof(sccno));
41         memset(pre,0,sizeof(pre));
42 }
43 
44     void addEdge1(int x, int y){//x*y=false
45         to[ecnt] = y^1; next[ecnt] = head[x]; head[x] = ecnt++;
46         to[ecnt] = x^1; next[ecnt] = head[y]; head[y] = ecnt++;
47 }
48 
49     boolsolve(){
50         for(int i = 0; i < n; ++i)
51             if(!pre[i]) dfs(i);
52         for(int i = 0; i < n; i += 2)
53             if(sccno[i] == sccno[i^1]) return false;
54         return true;
55 }
56 } G;
57 
58 intmain(){
59     intn, m, a, b, c, d;
60     while(scanf("%d%d",&n,&m)!=EOF){
61         G.init(2*n);
62         while(m--){
63             scanf("%d%d%d%d",&a,&b,&c,&d);
64             G.addEdge1(a*2 + c, b*2 +d);
65 }
66         if(G.solve()) printf("YES
");
67         else printf("NO
");
68 }
69     return 0;
70 }
tarjan

免责声明:文章转载自《HDU 3062 Party(2-SAT模版题)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇WebStorm常用快捷键总结解决鼠标滚动的时候多次执行函数下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

图上的文章(割点和桥)

题外话: 今天不想码代码了,知识普及的一天 注意:以下内容是在无向图的基础上 无向图的割点很久之前就知道这些名词 今天终于可以来填坑了。。。 如果将连通图G中的某个点及和这个点相关的边删除后,将使连通分量数量增加,那么这个点就称为图G的割点或是接合点。 如果一个无向图没有割点,则这样的图被称为双连通图。 关于图的割点,有如下两条性质: 【性质一】 如果...

剪枝策略

剪枝,顾名思义,就是通过一些判断,砍掉搜索树上不必要的子树。有时候,我们会发现某个结点对应的子树的状态都不是我们要的结果,那么我们其实没必要对这个分支进行搜索,砍掉这个子树,就是剪枝。 可行性剪枝 给定n个整数,要求选出K个数,使得选出来的K个数的和为sum。 在搜索时,如果已经选了k个数,再往后选多的数是没有意义的。所以我们可以直接减去这个搜索分支。 又...

1030 Travel Plan (30 分)(最短路径 and dfs)

#include<bits/stdc++.h> using namespace std; const int N=510; const int inf=0x3f3f3f3f; int mp[N][N]; bool vis[N]; int dis[N]; int n,m,s,D; int cost[N][N]; vector<int&g...

UVA 690 PipelineScheduling 位运算+dfs+剪枝

一开始最容易想到间隔最多为n,但是结点还是太多了,需要优化。 预处理:预判一下并保存下一个可以放的位置距离之前的距离。这样可以减少很多判断。 最优化剪枝:如果当前长度+剩下没放的程序*最短间隔如果大于等于ans,那么对答案没有贡献,可以剪去。 优化:占用和不占用两种状态,如果横向来看可以压缩为int,判断时用上为运算。 此题挂在长度的枚举上,我把长度为n给...

算法总结—深度优先搜索DFS

深度优先搜索(DFS) 往往利用递归函数实现(隐式地使用栈)。 深度优先从最开始的状态出发,遍历所有可以到达的状态。由此可以对所有的状态进行操作,或列举出所有的状态。 1.poj2386 Lake Couting 题意:八连通被认为连接在一起,求总共有多少个水洼? Sample Input: 10 12 W........WW. .WWW.....WWW...

欧拉回路(fleuru算法实现)

书上的欧拉回路定义不在重复,欧拉回路定义, 弗洛莱走边的方法也不再细讲,弗洛莱算法描述 这里只说怎么进行代码实现。 /* 无向图的欧拉回路 邻接矩阵存图 原理: dfs走边,当走不动时就将其放入栈中,最后将顶点从栈中取出的顺序就是欧拉路径。 如果走错边则必定会堵,那么就会将堵的放入栈中,从栈中取出的话就看作是最后走的割边,符合弗洛来算法; 如果走的...