天天看點

uva1391Astronauts【2-SAT】

又是劉汝佳書上的題,貌似書上隻有這兩個了,确實2-SAT的題也沒有太多,看邝斌的分類也才九個,今天加明天上午再A兩個就結束~

做這個題的時候發現自己對于結點的表示還是不夠了解,遂把四種情況都列出來

xi為假 或xj為假 2*i+1==>2*j 2*j+1==>2*i
xi為真或xj為真 2*i==>2*j+1 2*j==>2*i+1
xi為假或xj為真 2*i+1==>2*j+1 2*j==>2*i
xi為真或xj為假 2*i==>2*j 2*j+1==>2*i+1

上一個飛機排程的題發現兩種情況的沖突了,是以改變其中一個,變成了上表中後兩種情況(發現沖突肯定不能同時改變)

這個宇航員完成任務,限制的條件是互相讨厭的不能去同一個任務,就算不是同樣年齡分組的,也不可以同時去C,那麼相同年齡分組的就不可以同時去那個A還是B啊。我們假設去A、B是xi=true 去C是xi=true,那麼不能同時去C就是和飛機排程一樣solver.add_clause(a,1,b,1);,不能同時去A、B就是solver.add_clause(a,0,b,0); 而且感覺從連邊的思想上講,這個題比宇航員好想

/************
uva1391
2016.1.11
255	C++ 4.8.2
************/
#include <iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
#define maxn 100004
struct TwoSAT{
    int n;
    vector<int>G[maxn*2];
    bool mark[maxn*2];
    int S[maxn*2],c;
    bool dfs(int x){
        if(mark[x^1]) return false;
        if(mark[x]) return true;
        mark[x]=true;
        S[c++]=x;
        for(int i=0;i<G[x].size();i++)
            if(!dfs(G[x][i])) return false;
        return true;
    }
    void init(int n){
        this->n=n;
        for(int i=0;i<(n<<1);i++) G[i].clear();
        memset(mark,0,sizeof(mark));
    }
    void add_clause(int x,int xval,int y,int yval){
        x=x*2+xval;
        y=y*2+yval;
        G[x^1].push_back(y);
        G[y^1].push_back(x);
    }
    bool solve(){
        for(int i=0;i<n*2;i+=2)
        if(!mark[i]&&!mark[i+1]){
            c=0;
            if(!dfs(i)){
                while(c>0) mark[S[--c]]=false;
                if(!dfs(i+1)) {
                    mark[i]=false;
                    mark[i+1]=true;
                    return false;
                }
            }
        }
        return true;
    }
}solver;
int n,m,sum;
int age[maxn];
int is_young(int x)
{
    return age[x]*n<sum;
}
int main()
{
  //  freopen("cin.txt","r",stdin);
    while(~scanf("%d%d",&n,&m))
    {
        if(n==0&&m==0) break;
        sum=0;
        for(int i=0;i<n;i++) {
            scanf("%d",&age[i]);
            sum+=age[i];
        }
        solver.init(n);///
        for(int i=0;i<m;i++)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            a--;b--;
            if(a==b) continue;
            solver.add_clause(a,1,b,1);
            if(is_young(a)==is_young(b))
                solver.add_clause(a,0,b,0);
        }
        if(!solver.solve())
            printf("No solution\n");
        else
        {
            for(int i=0;i<n;i++)
            {
                if(solver.mark[i<<1]) puts("C");
                else if(is_young(i)) puts("B");
                else puts("A");
            }
        }
    }
    return 0;
}