訓練指南 UVALive - 3713 (2-SAT)
阿新 • • 發佈:2019-01-31
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)