挑战程序竞赛系列(78):4.3 2-SAT(2)
来源:互联网 发布:protobuf c windows 编辑:程序博客网 时间:2024/06/06 03:39
挑战程序竞赛系列(78):4.3 2-SAT(2)
传送门:POJ 3678: Katu Puzzle
题意:
某组合电路有N个输入,M个与或异或门将其两两相连构成多个输出,问是否存在满足给定输出的输入。
思路:
2-SAT模型都是解题套路,对于每一条边,如 0 1 1 AND:
ANDa b 0 0 00 1 01 0 01 1 1给定c = 1,说明 0-0,0-1,1-0的关系矛盾,据此加边:2 * a, 2 * b 等价于 02 * a + 1 , 2 * b + 1等价于 1scc.add(2 * a, 2 * b + 1);scc.add(2 * b, 2 * a + 1);scc.add(2 * a, 2 * b);scc.add(2 * b + 1, 2 * a + 1);scc.add(2 * a + 1, 2 * b + 1);scc.add(2 * b, 2 * a);给定c = 0,说明 1-1关系矛盾,据此加边:scc.add(2 * a + 1, 2 * b);scc.add(2 * b + 1, 2 * a);异或,或同理。
代码如下:
import java.io.BufferedReader;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.PrintWriter;import java.util.ArrayList;import java.util.Arrays;import java.util.List;import java.util.StringTokenizer;public class Main{ String INPUT = "./data/judge/201709/P3678.txt"; public static void main(String[] args) throws IOException { new Main().run(); } class SCC { static final int MAX_V = 1000 + 8; List<Integer>[] g = new List[MAX_V]; List<Integer>[] rg = new List[MAX_V]; List<Integer> po = new ArrayList<Integer>(); boolean[] used = new boolean[MAX_V]; int[] cmp = new int[MAX_V]; int V; SCC(int V) { this.V = V; po = new ArrayList<Integer>(); Arrays.fill(used, false); for (int i = 0; i < V; ++i) g[i] = new ArrayList<Integer>(); for (int i = 0; i < V; ++i) rg[i] = new ArrayList<Integer>(); } void add(int from, int to) { g[from].add(to); rg[to].add(from); } void dfs(int v) { used[v] = true; for (int u : g[v]) { if (!used[u]) dfs(u); } po.add(v); } void rdfs(int v, int k) { used[v] = true; cmp[v] = k; for (int u : rg[v]) { if (!used[u]) rdfs(u, k); } } int kosarajuSCC() { for (int v = 0; v < V; ++v) { if (!used[v]) dfs(v); } Arrays.fill(used, false); int k = 0; for (int i = po.size() - 1; i >= 0; --i) { int v = po.get(i); if (!used[v]) rdfs(v, k++); } return k; } } void read() { int N = ni(); int M = ni(); SCC scc = new SCC(N * 2); for (int i = 0; i < M; ++i) { int a = ni(); int b = ni(); int c = ni(); String op = ns(); if (op.equals("AND")) { if (c == 0) { scc.add(2 * a + 1, 2 * b); scc.add(2 * b + 1, 2 * a); } else { scc.add(2 * a, 2 * b + 1); scc.add(2 * b, 2 * a + 1); scc.add(2 * a, 2 * b); scc.add(2 * b + 1, 2 * a + 1); scc.add(2 * a + 1, 2 * b + 1); scc.add(2 * b, 2 * a); } } else if (op.equals("OR")) { if (c == 0) { scc.add(2 * a, 2 * b); scc.add(2 * b + 1, 2 * a + 1); scc.add(2 * a + 1, 2 * b + 1); scc.add(2 * b, 2 * a); scc.add(2 * a + 1, 2 * b); scc.add(2 * b + 1, 2 * a); } else { scc.add(2 * a, 2 * b + 1); scc.add(2 * b, 2 * a + 1); } } else { if (c == 0) { scc.add(2 * a, 2 * b); scc.add(2 * b + 1, 2 * a + 1); scc.add(2 * a + 1, 2 * b + 1); scc.add(2 * b, 2 * a); } else { scc.add(2 * a, 2 * b + 1); scc.add(2 * b, 2 * a + 1); scc.add(2 * a + 1, 2 * b); scc.add(2 * b + 1, 2 * a); } } } scc.kosarajuSCC(); for (int i = 0; i < N; ++i) { if (scc.cmp[2 * i] == scc.cmp[2 * i + 1]) { out.println("NO"); return; } } out.println("YES"); } FastScanner in; PrintWriter out; void run() throws IOException { boolean oj; try { oj = ! System.getProperty("user.dir").equals("F:\\java_workspace\\leetcode"); } catch (Exception e) { oj = System.getProperty("ONLINE_JUDGE") != null; } InputStream is = oj ? System.in : new FileInputStream(new File(INPUT)); in = new FastScanner(is); out = new PrintWriter(System.out); long s = System.currentTimeMillis(); read(); out.flush(); if (!oj){ System.out.println("[" + (System.currentTimeMillis() - s) + "ms]"); } } public boolean more(){ return in.hasNext(); } public int ni(){ return in.nextInt(); } public long nl(){ return in.nextLong(); } public double nd(){ return in.nextDouble(); } public String ns(){ return in.nextString(); } public char nc(){ return in.nextChar(); } class FastScanner { BufferedReader br; StringTokenizer st; boolean hasNext; public FastScanner(InputStream is) throws IOException { br = new BufferedReader(new InputStreamReader(is)); hasNext = true; } public String nextToken() { while (st == null || !st.hasMoreTokens()) { try { st = new StringTokenizer(br.readLine()); } catch (Exception e) { hasNext = false; return "##"; } } return st.nextToken(); } String next = null; public boolean hasNext(){ next = nextToken(); return hasNext; } public int nextInt() { if (next == null){ hasNext(); } String more = next; next = null; return Integer.parseInt(more); } public long nextLong() { if (next == null){ hasNext(); } String more = next; next = null; return Long.parseLong(more); } public double nextDouble() { if (next == null){ hasNext(); } String more = next; next = null; return Double.parseDouble(more); } public String nextString(){ if (next == null){ hasNext(); } String more = next; next = null; return more; } public char nextChar(){ if (next == null){ hasNext(); } String more = next; next = null; return more.charAt(0); } }}
阅读全文
0 0
- 挑战程序竞赛系列(78):4.3 2-SAT(2)
- 挑战程序竞赛系列(77):4.3 2-SAT(1)
- 挑战程序竞赛系列(79):4.3 2-SAT(3)
- 挑战程序竞赛系列(80):4.3 2-SAT(4)
- 挑战程序竞赛系列(82):4.3 LCA(2)
- 挑战程序竞赛系列(75):4.3强连通分量分解(2)
- 挑战程序竞赛系列(81):4.3 LCA(1)
- 挑战程序竞赛系列(27):3.5二分图匹配(2)
- 挑战程序竞赛系列(39):4.1模运算的世界(2)
- 挑战程序竞赛系列(46):4.1Polya 计数定理(2)
- 挑战程序竞赛系列(49):4.2 推理与动态规划算法(2)
- 挑战程序竞赛系列(55):4.4 双端队列(2)
- 挑战程序竞赛系列(59):4.6树上的分治法(2)
- 挑战程序竞赛系列(62):4.6平面上的分治法(2)
- 挑战程序竞赛系列(64):4.7字符串上的动态规划(2)
- 挑战程序竞赛系列(67):4.7字符串匹配(2)
- 挑战程序竞赛系列(70):4.7后缀数组(2)
- 挑战程序竞赛系列(72):4.7高度数组(2)
- 初学JS小记(一)——变量的作用域
- JS中避免命名冲突
- 极光推送
- Spark Programming Guide(五)
- 求俩个数的和,要求不能用加减乘除四则运算。
- 挑战程序竞赛系列(78):4.3 2-SAT(2)
- android 自动化测试
- [Python] 500万彩票网微信推送中奖号码
- python开源库——h5py快速指南
- HDU
- 浅谈MapMatrix系统下DEM和DOM的制作方法
- 用深度学习做个艺术画家 ——模仿实现PRISMA
- Camel
- 自定义View实现listView的左划删除