zoukankan      html  css  js  c++  java
  • COGS:313. [POI2001] 和平委员会

    313. [POI2001] 和平委员会

    ★★☆   输入文件:spo.in   输出文件:spo.out   评测插件
    时间限制:1 s   内存限制:128 MB

    题目描述

    根据宪法,Byteland民主共和国的公众和平委员会应该在国会中通过立法程序来创立。 不幸的是,由于某些党派代表之间的不和睦而使得这件事存在障碍。

    此委员会必须满足下列条件:

    • 每个党派都在委员会中恰有1个代表,
    • 如果2个代表彼此厌恶,则他们不能都属于委员会。

    每个党在议会中有2个代表。代表从1编号到2n。 编号为2i-1和2i的代表属于第I个党派。

    任务

    写一程序:

    • 从文本文件读入党派的数量和关系不友好的代表对,
    • 计算决定建立和平委员会是否可能,若行,则列出委员会的成员表,
    • 结果写入文本文件。

    输入

    在文本文件的第一个行有2非负整数n和m。 他们各自表示:党派的数量n,1 < =n < =8000和不友好的代表对m,0 <=m <=20000。 在下面m行的每行为一对整数a,b,1<=a<b<=2n,中间用单个空格隔开。 p="" 它们表示代表a,b互相厌恶。<="">

    输出

    如果委员会不能创立,文本文件中应该包括单词NIE。若能够成立,文本文件SPO.OUT中应该包括n个从区间1到2n选出的整数,按升序写出,每行一个,这些数字为委员会中代表的编号。如果委员会能以多种方法形成,程序可以只写他们的某一个。

    样品输入

    3 2
    1 3
    2 4
    

    样品输出

    1
    4
    5



    分析

    2-sat问题模板题。

    算法实现:

    1. 连边
    2. tarjan
    3. 判可行性,即同一集合中的两个点是否同属一个强连通块
    4. 缩点建新图,连反边
    5. 拓扑序,若当前点没有被访问过,则选择该点,不选择其另外的点

    详细的文章中有,文章 :http://blog.csdn.net/jarjingx/article/details/8521690

    code

      1 #include<cstdio>
      2 #include<algorithm>
      3 #include<cstring>
      4 #include<cmath>
      5 #include<vector>
      6 
      7 #define oth(x) x&1?x+1:x-1
      8 
      9 using namespace std;
     10 
     11 const int N = 20010;
     12 
     13 struct Edge{
     14     int to,nxt;
     15 }e[50010];
     16 int head[N],dfn[N],low[N],st[N],bel[N];
     17 bool vis[N];
     18 int ru[N],q[N],opp[N],pr[N];
     19 int tot_edge,n,nn,m,tot_node,top,cnt_block,L,R;
     20 vector<int>mp[N];
     21 
     22 inline char nc() {
     23     static char buf[100000],*p1 = buf,*p2 = buf;
     24     return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
     25 }
     26 inline int read() {
     27     int x = 0,f = 1;char ch = nc();
     28     for (; ch<'0'||ch>'9'; ch=nc()) if(ch=='-') f=-1;
     29     for (; ch>='0'&&ch<='9'; ch=nc()) x=x*10+ch-'0';
     30     return x * f;
     31 }
     32 
     33 void add_edge(int u,int v) {
     34     e[++tot_edge].to = v;e[tot_edge].nxt = head[u];head[u] = tot_edge;
     35 }
     36 
     37 void tarjan(int u) {
     38     dfn[u] = low[u] = ++tot_node;
     39     st[++top] = u;
     40     vis[u] = true;
     41     for (int i=head[u]; i; i=e[i].nxt) {
     42         int v = e[i].to;
     43         if (!dfn[v]) {
     44             tarjan(v);
     45             low[u] = min(low[v],low[u]);
     46         }
     47         else if (vis[v]) 
     48             low[u] = min(dfn[v],low[u]);
     49     }
     50     if (low[u] == dfn[u]) {
     51         ++cnt_block;
     52         do {
     53             vis[st[top]] = false;
     54             bel[st[top]] = cnt_block;
     55             top--;
     56         } while (st[top+1] != u);
     57     }
     58 }
     59 void toposort() {
     60     L = 1;R = 0;
     61     for (int i=1; i<=cnt_block; ++i) 
     62         if (ru[i]==0) q[++R] = i;
     63     while (L <= R) {
     64         int u = q[L++];
     65         if (pr[u] != 0) continue;
     66         pr[u] = 1;pr[opp[u]] = 2;
     67         int sz = mp[u].size();
     68         for (int i=0; i<sz; ++i) {
     69             int v = mp[u][i];
     70             ru[v]--;
     71             if (ru[v]==0) q[++R] = v;
     72         }
     73     }
     74 }
     75 bool work() {
     76     for (int i=1; i<=nn; ++i) {
     77         if (!dfn[i]) tarjan(i);
     78     }
     79     for (int i=1; i<=nn; ++i) {
     80         if (bel[i] == bel[oth(i)]) return false;
     81         opp[bel[i]] = bel[oth(i)];
     82         opp[bel[oth(i)]] = bel[i];
     83     }
     84     for (int u=1; u<=nn; ++u) {
     85         for (int i=head[u]; i; i=e[i].nxt) {
     86             int v = e[i].to;
     87             if (bel[u] != bel[v]) {
     88                 ru[bel[u]] ++;
     89                 mp[bel[v]].push_back(bel[u]);
     90             }
     91         }
     92     }
     93     toposort();
     94     return true;
     95 }
     96 int main () {
     97     freopen("spo.in","r",stdin);
     98     freopen("spo.out","w",stdout);
     99     n = read(),m = read();nn = n<<1;
    100     for (int i=1; i<=m; ++i) {
    101         int a = read(),b = read();
    102         add_edge(a,oth(b));
    103         add_edge(b,oth(a));
    104     }
    105     if (work()) {
    106         for (int i=1; i<=nn; ++i) 
    107             if (pr[bel[i]]==1) printf("%d
    ",i); //-
    108     }
    109     else puts("NIE");
    110     return 0;
    111 }
    View Code

    再放一发搜索代码

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 
     5 #define others(x) x&1?x+1:x-1
     6 
     7 using namespace std;
     8 
     9 const int N = 20010;
    10 
    11 struct Edge{
    12     int to,nxt;
    13 }e[50010];
    14 int head[N],mark[N],q[N];
    15 int tot,c,n,m;
    16 
    17 inline char nc() {
    18     static char buf[100000],*p1 = buf,*p2 = buf;
    19     return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
    20 }
    21 inline int read() {
    22     int x = 0,f = 1;char ch = nc();
    23     for (; ch<'0'||ch>'9'; ch=nc()) if(ch=='-') f=-1;
    24     for (; ch>='0'&&ch<='9'; ch=nc()) x=x*10+ch-'0';
    25     return x * f;
    26 }
    27 
    28 void add_edge(int u,int v) {
    29     e[++tot].to = v;e[tot].nxt = head[u];head[u] = tot;
    30 }
    31 bool dfs(int u) {
    32     if (mark[u] != 0) return mark[u] % 2;
    33     mark[u] = 1;mark[others(u)] = 2;
    34     q[++c] = u;
    35     for (int i=head[u]; i; i=e[i].nxt) {
    36         int v = e[i].to;
    37         if (!dfs(v)) return false;
    38     }
    39     return true;
    40 }
    41 bool work() {
    42     for (int i=1; i<=(n<<1); ++i) {
    43         if (mark[i]) continue;
    44         c = 0;
    45         if (!dfs(i)) {
    46             for (int j=1; j<=c; ++j) 
    47                 mark[q[j]] = mark[others(q[j])] = 0;
    48             if (!dfs(others(i))) return false;
    49         }
    50     }
    51     return true;
    52 }
    53 
    54 int main () {
    55     freopen("spo.in","r",stdin);
    56     freopen("spo.out","w",stdout);
    57     n = read(),m = read();
    58     for (int i=1; i<=m; ++i) {
    59         int a = read(),b = read();
    60         add_edge(a,others(b));
    61         add_edge(b,others(a));
    62     }
    63     if (work()) {
    64         for (int i=1; i<=(n<<1); ++i) 
    65             if (mark[i]==1) printf("%d
    ",i);
    66     }
    67     else puts("NIE");
    68     return 0;
    69 }
    View Code
  • 相关阅读:
    准备工作:安装Arduino驱动(Windows)
    关于osEye的URL设计
    Debian 6.0下安装Memcached
    准备工作:购买Arduino
    debian6.0安装后中文字体显示不正常的解决办法
    取消UL和OL符号以及padding和margin后恢复默认值的CSS
    linux中reboot、shutdown、halt等命令详细讲解
    IIS6中应用程序池和Web园,解决Session丢失问题
    [z]C# winForm 程序调用 Java WebService
    [z]HTMLTextBox
  • 原文地址:https://www.cnblogs.com/mjtcn/p/8457935.html
Copyright © 2011-2022 走看看