zoukankan      html  css  js  c++  java
  • [POI2001]Peaceful Commission

    题目大意:
      有n个国家要派代表开会,每个国家有两个代表可供选择。
      有m对代表有仇,不能同时开会。
      若每个国家只能派一个代表开会,问是否存在一种方案,使得每个国家都能正常参会?
      如果有,输出字典序最小的一种。

    思路:
      2-SAT经典模型。
      如果两个代表之间有仇,那么就给其中一个代表a连一条通向另一国家另一代表b的有向边,表示选a后一定要选b。
      判定时就用Tarjan缩点,如果同一国家两个代表在同一个强连通分量中,那么说明两个代表必须同时参加或不参加,这是不合法的。
      构造字典序最小的方案时,可以从小到大枚举每一个代表,然后DFS选定该代表后,必须选的其它代表,如果必须选的的代表和已选代表矛盾,则不加入。

     1 #include<stack>
     2 #include<cstdio>
     3 #include<cctype>
     4 #include<vector>
     5 inline int getint() {
     6     register char ch;
     7     while(!isdigit(ch=getchar()));
     8     register int x=ch^'0';
     9     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    10     return x;
    11 }
    12 const int N=16000;
    13 std::stack<int> s;
    14 std::vector<int> e[N<<1];
    15 bool ins[N<<1],select[N<<1];
    16 int dfn[N<<1],low[N<<1],scc[N<<1],cnt,id;
    17 inline void add_edge(const int &u,const int &v) {
    18     e[u].push_back(v);
    19 }
    20 void tarjan(const int &x) {
    21     s.push(x);
    22     ins[x]=true;
    23     dfn[x]=low[x]=++cnt;
    24     for(unsigned i=0;i<e[x].size();i++) {
    25         const int &y=e[x][i];
    26         if(!dfn[y]) {
    27             tarjan(y);
    28             low[x]=std::min(low[x],low[y]);
    29         } else if(ins[y]) {
    30             low[x]=std::min(low[x],dfn[y]);
    31         }
    32     }
    33     if(low[x]==dfn[x]) {
    34         id++;
    35         int y=-1;
    36         while(y!=x) {
    37             y=s.top();
    38             s.pop();
    39             ins[y]=false;
    40             scc[y]=id;
    41         }
    42     }
    43 }
    44 bool dfs(const int &x) {
    45     if(select[x^1]) return false;
    46     s.push(x);
    47     select[x]=true;
    48     for(unsigned i=0;i<e[x].size();i++) {
    49         const int &y=e[x][i];
    50         if(select[y]) continue;
    51         if(!dfs(y)) return false;
    52     }
    53     return true;
    54 }
    55 inline void reset(const int &n) {
    56     cnt=id=0;
    57     for(register int i=0;i<n<<1;i++) {
    58         dfn[i]=low[i]=select[i]=0;
    59         e[i].clear();
    60     }
    61 }
    62 int main() {
    63     int n,m;
    64     while(~scanf("%d%d",&n,&m)) {
    65         while(m--) {
    66             const int u=getint()-1,v=getint()-1;
    67             add_edge(u,v^1);
    68             add_edge(v,u^1);
    69         }
    70         for(register int i=0;i<n<<1;i++) {
    71             if(!dfn[i]) tarjan(i);
    72         }
    73         for(register int i=0;i<n;i++) {
    74             if(scc[i<<1]==scc[i<<1|1]) {
    75                 puts("NIE");
    76                 goto Next;
    77             }
    78         }
    79         for(register int i=0;i<n<<1;i++) {
    80             if(!select[i]&&!select[i^1]) {
    81                 if(dfs(i)) {
    82                     while(!s.empty()) s.pop();
    83                 } else {
    84                     while(!s.empty()) {
    85                         const int x=s.top();
    86                         s.pop();
    87                         select[x]=false;
    88                     }
    89                 }
    90             }
    91         }
    92         for(register int i=0;i<n<<1;i++) {
    93             if(select[i]) printf("%d
    ",i+1);
    94         }
    95         Next:
    96             reset(n);
    97     }
    98     return 0;
    99 }
  • 相关阅读:
    sweetalert 1.0多次回调函数bug
    ThinkPHP添加扩展配置失败
    记一次相机内存卡数据恢复
    流量监控脚本监控网卡
    ip网关配置
    centos7【防火墙】常用规则-docker服务防火墙规则
    ssh服务及安全配置
    代码库
    linux计划任务防暴力破解脚本+免密操作
    阿里去短信接口包
  • 原文地址:https://www.cnblogs.com/skylee03/p/8183281.html
Copyright © 2011-2022 走看看