UVALive 3713 Astronauts (2-SAT,变形)

 

题意:有A,B,C三种任务,每个人必获得1个任务,大于等于平均年龄的可以选择A和C,小于平均年龄的可以选择B和C。这些人有一些是互相讨厌的,必须不能执行同任务,问能否安排他们工作?若行,输出任意一组解。

思路:

  依然是 2-SAT,只不过换了个样子,建图时不同而已。这里每个人依然有2人选择,也有冲突的出现,问题在如何找出冲突。

  首先,无论是哪两人,只要互相讨厌,去抢C,必定冲突。其次,如果是同龄人(同大于等于,或同小于),那么抢他们那个年龄段的任务也会冲突。所以共计2种,每种2条边,即我选的时候,你不能选;你选的时候,我不能选。

  在建好图后,进行DFS进行尝试一组可行解,所有尝试都不行时,就No Solution。有解时,如果2*i为true,那么输出时要判断这个人的年龄,给他分配对应年龄段的任务;如果i*2+1为true,那么这个人是选C的,不关年龄事直接输出。

  

 

  

  1 #include <iostream>

  2 #include <stdio.h>

  3 #include <string.h>

  4 #include <vector>

  5 #include <stack>

  6 #include <algorithm>

  7 

  8 #include <bits/stdc++.h>

  9 #define LL long long

 10 #define pii pair<int,int>

 11 #define INF 0x7f7f7f7f

 12 using namespace std;

 13 const int N=100000*2+5;

 14 int age[N], n, m, col[N],s[N],c;

 15 double even;

 16 vector<int> vect[N];

 17 

 18 bool isolder(int x)

 19 {

 20     return x>=even? 1: 0;

 21 }

 22 void add_edge(int i,int j)  //建图

 23 {

 24     //x*2+1的表示选择c,x*2表示选择非c

 25     vect[i*2+1].push_back(j*2);         //无论哪两人,抢c必有冲突

 26     vect[j*2+1].push_back(i*2);

 27 

 28     if(isolder(age[i])==isolder(age[j]))  //抢A或B有冲突

 29     {

 30         vect[i*2].push_back(j*2+1);

 31         vect[j*2].push_back(i*2+1);

 32     }

 33 }

 34 

 35 bool color(int x)

 36 {

 37     if(col[x^1])    return false;

 38     if(col[x])      return true;

 39     col[x]=1;

 40     s[c++]=x;

 41     for(int i=0; i<vect[x].size(); i++)

 42     {

 43         int t=vect[x][i];

 44         if(!color(t)) return false;

 45     }

 46     return true;

 47 }

 48 

 49 bool cal(int n)

 50 {

 51     memset(col,0,sizeof(col));

 52     memset(s,0,sizeof(s));

 53     for(int i=0; i<n; i+=2)

 54     {

 55         if(!col[i]&&!col[i+1])

 56         {

 57             c=0;

 58             if(!color(i))

 59             {

 60                 while(c)    col[s[--c]]=0;

 61                 if(!color(i+1))    return false;

 62             }

 63         }

 64     }

 65     return true;

 66 }

 67 

 68 

 69 

 70 int main()

 71 {

 72     freopen("input.txt", "r", stdin);

 73     int a,b;

 74     while(scanf("%d%d",&n,&m),n+m)

 75     {

 76         for(int i=n*2; i>=0; i--)   vect[i].clear();

 77         even=0.0;

 78         for(int i=0; i<n; i++)

 79         {

 80             scanf("%d",&age[i]);

 81             even+=age[i];

 82         }

 83         even/=n;

 84 

 85         for(int i=0; i<m; i++)

 86         {

 87             scanf("%d%d",&a,&b);

 88             add_edge(--a,--b);

 89         }

 90 

 91         if(!cal(n<<1))    puts("No solution.");

 92         else

 93         {

 94             for(int i=0; i<n; i++)  //随便输出一组合法解。

 95             {

 96                 if(col[i*2])

 97                 {

 98                     if(isolder(age[i]) )      puts("A");

 99                     else    puts("B");

100                 }

101                 else puts("C");

102             }

103         }

104     }

105     return 0;

106 }
AC代码

 

你可能感兴趣的:(live)