LA 3713 Astronauts

来源:互联网 发布:linux解析文件 编辑:程序博客网 时间:2024/05/20 05:11
这同样是一个2—sat 加建图的问题。

建图是有一个关键点:只有某种情况是“唯一”、“确定”是才能对这种情况进行连边 。切记 , 这点在所有建图中都很关键 ,往往出错就是在这出的错 。 这题就是一个很好的例子 。

首先可以确定 , 每个宇航员只有两种选择 , 假设宇航员 a 、 b , 的年龄一个大于平均 , 一个小于平均,那么连边是就只要连接当a选 c任务时 , b 就不能选 c 任务 , 反过来也是 , 而没必要连接当a 不选c任务时的情况 ,因为此时的情况是不确定的 , 也就是没有唯一性 。

代码:
#include
#include
#include
#include
#include
#include
#include
using namespace std;

const int MAXN = 100010 ;
vectorgrap[MAXN*2] ;  // 存储建的图
bool mark[MAXN*2] ;  // 标记已经确定任务的宇航员
int age[MAXN] , s[MAXN*2] , n = 0, m = 0, c ;

void init()
{
    for(int i =0 ; i < n*2 ; i++)
      grap[i].clear();
    memset(mark, 0 , sizeof(mark));
   
    c = 0;
}

bool dfs(int x)
{
   if(mark[x^1])  return false;  //如果一个宇航员连个任务都被标记了 , 那么这是不可以 , 也就是false
   if(mark[x])  return true;
    mark[x] =true ;
    s[c++] =x;
    for(int i =0 ; i < grap[x].size() ; i++)
      if(!dfs(grap[x][i]))  return false;
    return true;
}

bool solve()
{
    for(int i =0 ; i < 2*n; i += 2)
    {
       if(!mark[i]&& !mark[i+1])
       {
          c = 0;
         if(!dfs(i))
          {
             while(c >0)  mark[s[--c]] = false ;
            if(!dfs(i+1))  return false;
          }
       }
    }
    return true;
}

int main()
{
   while(scanf("%d %d" , &n , &m) != EOF)
    {
      init();
      if(!n&&!m)  break;
       int i , sum= 0;
       for(i = 0 ;i < n; i++)
       {
          scanf("%d" ,&age[i]);
          sum +=age[i];
       }
       double p_age= (double)sum/n ;
       int x ,y;
       for(i = 0 ;i < m; i++)
       {
          scanf("%d%d" , &x , &y);
          x -=1;
          y -=1;
         if((age[x]=p_age && age[y]>=p_age))  //建图
          {
            grap[x*2].push_back(y*2+1);  // 两个年龄相同时 , 只能选不同的一个。
            grap[y*2+1].push_back(x*2);
            grap[y*2].push_back(x*2+1);
            grap[x*2+1].push_back(y*2);
          }
          else
          {
            grap[y*2+1].push_back(x*2); // 两个年龄相同时,只需要连接可以确定的、唯一的边。
            grap[x*2+1].push_back(y*2);
            
          }
       }
       bool bz =solve();
      if(bz)  //  输出每个宇航员的任务
       {
          for(i = 0 ;i < 2*n ; i += 2)
          {
             x =i/2;
            if(mark[i])
             {
                if(age[x]>= p_age)  printf("A\n");
                elseprintf("B\n");
             }
             elseif(mark[i+1])  printf("C\n");
          }
       }
      else  printf("No solution \n");
    }
    return0;
}
0 0
原创粉丝点击