【 HDU - 3062】Party(2-sat)
題干:
有n對(duì)夫妻被邀請(qǐng)參加一個(gè)聚會(huì),因?yàn)閳?chǎng)地的問題,每對(duì)夫妻中只有1人可以列席。在2n 個(gè)人中,某些人之間有著很大的矛盾(當(dāng)然夫妻之間是沒有矛盾的),有矛盾的2個(gè)人是不會(huì)同時(shí)出現(xiàn)在聚會(huì)上的。有沒有可能會(huì)有n 個(gè)人同時(shí)列席?
Input
n: 表示有n對(duì)夫妻被邀請(qǐng) (n<= 1000)?
m: 表示有m 對(duì)矛盾關(guān)系 ( m < (n - 1) * (n -1))?
在接下來的m行中,每行會(huì)有4個(gè)數(shù)字,分別是 A1,A2,C1,C2?
A1,A2分別表示是夫妻的編號(hào)?
C1,C2 表示是妻子還是丈夫 ,0表示妻子 ,1是丈夫?
夫妻編號(hào)從 0 到 n -1?
Output
如果存在一種情況 則輸出YES?
否則輸出 NO?
Sample Input
2 1 0 1 1 1Sample Output
YES解題報(bào)告:
? ?直接2-sat裸題。因?yàn)轭}干中說一對(duì)夫妻有且只有一個(gè)人參加聚會(huì),所以符合元素和元素的非 的性質(zhì)。所以如果說A和B有仇,那就A->b , B -> a這樣就好。
AC代碼:
#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define F first #define S second #define ll long long #define pb push_back #define pm make_pair using namespace std; typedef pair<int,int> PII; const int MAX = 3000 + 5; struct Edge {int v,ne; } e[5000005]; int n,m; int head[MAX],tot;//1~n代表妻子,n+1到2*n代表丈夫 void add(int u,int v) {e[++tot].v = v;e[tot].ne = head[u];head[u] = tot; } int DFN[MAX],LOW[MAX],col[MAX],vis[MAX],index,stk[MAX],scc,clk; void Tarjan(int x) {DFN[x] = LOW[x] = ++clk;vis[x] = 1;stk[++index] = x;for(int i = head[x]; ~i; i = e[i].ne) {int v = e[i].v;if(!DFN[v]) {Tarjan(v);LOW[x] = min(LOW[x],LOW[v]);}else if(vis[v]) LOW[x] = min(LOW[x],DFN[v]);}if(LOW[x] == DFN[x]) {scc++;while(1) {int tmp = stk[index--];col[tmp] = scc;vis[tmp] = 0;if(tmp == x) break;}} } void init(int n) {tot=0;clk=index=scc=0;for(int i = 1; i<=2*n; i++) head[i] = -1,DFN[i]=LOW[i]=vis[i]=col[i]=0; } int main() {while(~scanf("%d%d",&n,&m)) {init(n);for(int c1,c2,a1,a2,i = 1; i<=m; i++) {scanf("%d%d%d%d",&a1,&a2,&c1,&c2);a1++,a2++;int U = a1 + c1*n,u=a1+(1-c1)*n;int V = a2 + c2*n,v=a2+(1-c2)*n;add(U,v);add(V,u); }for(int i = 1; i<=2*n; i++) {if(!DFN[i]) Tarjan(i);}int flag = 1;for(int i = 1; i<=n; i++) {if(col[i] == col[i+n]) {flag = 0;break;}}if(flag) puts("YES");else puts("NO");}return 0 ; } //20:10-20:39總結(jié):
當(dāng)然對(duì)于這一題還有另一種建圖方式:鏈接
對(duì)于這道題,我們首先要虛擬節(jié)點(diǎn),對(duì)于編號(hào)為i的妻子a和丈夫b,做法如下: (我用!來表示非,畢竟那些符號(hào)不好辦)
對(duì)妻子a: 對(duì)應(yīng)的a虛擬為 節(jié)點(diǎn) i ,對(duì)應(yīng)的!a虛擬為節(jié)點(diǎn) i + 2*N,?
對(duì)丈夫b: 對(duì)應(yīng)的b虛擬為節(jié)點(diǎn)i + N ,!b虛擬為節(jié)點(diǎn) i + N + 2*N。 這樣的話我們得到了4*N -1個(gè)節(jié)點(diǎn)。
由題意有以下建邊方案
一:夫妻a,b只能去一人且必須去一人。 得布爾表達(dá)式 (!a -> b)合取(!b -> a)合取(b -> !a)合取(a -> !b)
二:有矛盾的兩人不能同時(shí)去,這就意味著可能都不去。 得布爾表達(dá)式 (a -> !b)合取(b -> !a)
總結(jié)
以上是生活随笔為你收集整理的【 HDU - 3062】Party(2-sat)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 40年前存1万现在有多少钱?40年前存1
- 下一篇: 【UVA - 1335】Beijing