zoukankan      html  css  js  c++  java
  • Codeforces 776D:The Door Problem(DFS染色)

    http://codeforces.com/problemset/problem/776/D

    题意:有n个门,m个开关,每个门有一个当前的状态(0表示关闭,1表示打开),每个开关控制k个门,但是每个门确切的受两个开关控制,如果一个开关打开,那么原来关闭的门会打开,打开的门关闭,问是否存在一个情况使得所有的门打开。

    思路:类似于01染色,把开关当成点,门当前的状态当成边权建图。初始先假设一个门的状态(初始假设为0和假设为1都是一样的,举几个例子就发现了),然后因为每个门受两个开关控制,所以可以推出下一个门的状态,如果发现互斥的情况,那么就是“NO”。

    这里设成门状态0表示打开,1表示关闭,方便运算。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 #define N 200010
     4 struct Edge {
     5     int v, nxt, w;
     6 } edge[N*2];
     7 int col[N], fir[N], sec[N], head[N], tot, w[N];
     8 
     9 void Add(int u, int v, int w) {
    10     edge[tot] = (Edge) {v, head[u], w}; head[u] = tot++;
    11     edge[tot] = (Edge) {u, head[v], w}; head[v] = tot++;
    12 }
    13 
    14 bool dfs(int u) {
    15     for(int i = head[u]; ~i; i = edge[i].nxt) {
    16         int v = edge[i].v, w = edge[i].w;
    17         if(col[v] == -1) { // 如果这个开关没染色
    18             col[v] = col[u] ^ w;
    19             if(!dfs(v)) return false;
    20         } else if(col[u] ^ col[v] ^ w) return false; // 如果染过色并发生矛盾
    21     }
    22     return true;
    23 }
    24 
    25 int main() {
    26     int n, m;
    27     cin >> n >> m;
    28     for(int i = 1; i <= n; i++) scanf("%d", &w[i]), w[i] ^= 1;
    29     for(int i = 1; i <= m; i++) {
    30         int k; scanf("%d", &k);
    31         while(k--) {
    32             int a; scanf("%d", &a);
    33             if(fir[a] == 0) fir[a] = i; // 连a点的第一个开关
    34             else sec[a] = i; // 连a点的第二个开关
    35         }
    36     }
    37     memset(head, -1, sizeof(head)); tot = 0;
    38     for(int i = 1; i <= n; i++)
    39         Add(fir[i], sec[i], w[i]);
    40     memset(col, -1, sizeof(col));
    41     bool flag = 1;
    42     for(int i = 1; i <= m; i++) {
    43         if(col[i] == -1) {
    44             col[i] = 0; // 假设这个开关一开始是关的
    45             if(!dfs(i)) { flag = 0; break; }
    46         }
    47     }
    48     if(!flag) puts("NO");
    49     else puts("YES");
    50     return 0;
    51 }
  • 相关阅读:
    便利的开发文档工具doxygen
    父页面 js 取得弹出窗口所选择的值, 弹出窗口关闭后刷新父页面
    ASCII码对照表
    C#中Brush、Color、String相互转换
    C#获取标准北京时间
    2005数据库脚本在SQL2000上执行 注意事项
    给Image控件后台赋Source值
    Web服务枚举组件不可用
    泛型集合转化为DataSet
    网站常见关于"登录|注册"和"姓名|注销"用JS实现
  • 原文地址:https://www.cnblogs.com/fightfordream/p/6441216.html
Copyright © 2011-2022 走看看