1. 程式人生 > >訓練指南 UVALive - 3713 (2-SAT)

訓練指南 UVALive - 3713 (2-SAT)

bool 所有 itl clear -s cat code tdi oid


layout: post
title: 訓練指南 UVALive - 3713 (2-SAT)
author: "luowentaoaa"
catalog: true
mathjax: true
tags:
- 2-SAT
- 圖論
- 訓練指南


Astronauts

UVALive - 3713

題意

有A,B,C三個任務要分配個N個宇航員,每個宇航員恰好要分配一個任務,設平均年齡為X,只有年齡大於或等於X的宇航員才能分配任務A。只有年齡嚴格小於X的宇航員才能分配任務B。而任務C沒有限制。有M對宇航員相互討厭,因此不能分配到同一任務。編程找出一個滿足上述所有要求的任務分配方案。

題解

如果憎惡就代表不能一起去C,如果年齡相同就代表不能一起去A/B;

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=998244353;
const int maxn=1e6+50;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
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*2;i++)G[i].clear();
        memset(mark,0,sizeof(mark));
    }
    /// x=xval or y= yval;
    void add_caluse(int x,int xval,int y,int yval){
        x=x*2+xval;
        y=y*2+yval;
        G[x^1].push_back(y);///如果x為真 那麽y必須為假;
        G[y^1].push_back(x);///如果y為真 那麽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))return false;
            }
        }
        return true;
    }
};
int n,a[maxn],m;
TwoSAT solver;
int tol;
int is_young(int x){
    return a[x]*n<tol;
}
int main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);
    while(cin>>n>>m&&n&&m){
        tol=0;
        solver.init(n);
        for(int i=0;i<n;i++){
            cin>>a[i];
            tol+=a[i];
        }
        for(int i=0;i<m;i++){
            int a,b;
            cin>>a>>b;a--;b--;
            solver.add_caluse(a,1,b,1);
            if(is_young(a)==is_young(b))
                solver.add_caluse(a,0,b,0);
        }
        if(!solver.solve())cout<<"No solution."<<endl;
        else for(int i=0;i<n;i++)
            if(solver.mark[i*2])cout<<"C"<<endl;
        else if(is_young(i))cout<<"B"<<endl;
        else cout<<"A"<<endl;
    }
    return 0;
}

訓練指南 UVALive - 3713 (2-SAT)