Party(HDU-3062)
生活随笔
收集整理的這篇文章主要介紹了
Party(HDU-3062)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Problem Description
有n對夫妻被邀請參加一個聚會,因為場地的問題,每對夫妻中只有1人可以列席。在2n 個人中,某些人之間有著很大的矛盾(當然夫妻之間是沒有矛盾的),有矛盾的2個人是不會同時出現在聚會上的。有沒有可能會有n 個人同時列席?
Input
n: 表示有n對夫妻被邀請 (n<= 1000)
m: 表示有m 對矛盾關系 ( m < (n - 1) * (n -1))
在接下來的m行中,每行會有4個數字,分別是 A1,A2,C1,C2?
A1,A2分別表示是夫妻的編號?
C1,C2 表示是妻子還是丈夫 ,0表示妻子 ,1是丈夫
夫妻編號從 0 到 n -1?
Output
如果存在一種情況 則輸出YES?
否則輸出 NO?
Sample Input
2?
1
0 1 1 1?
Sample Output
YES
思路:每對夫妻代表圖中一個結點,只有 1、0 兩種選擇,對于有矛盾的夫妻對,使其不列席,讓無矛盾夫妻對的列席即可
對于 m 矛盾關系,設 a、b 兩對夫婦存在矛盾:
- 若第 a 對的妻子與第 b 對的妻子有矛盾(a b 0 0)
則 a 的妻子去了 b 的丈夫必須去,b 的妻子去了 a 的丈夫必須去:<a,0,b,1>、<b,0,a,1>,添邊:<a+n,b>,<b+n,a> - 若第 a 對的妻子與第 b 對的丈夫有矛盾(a b 0 1)
則 a 的妻子去了 b?的妻子必須去,b 的丈夫去了 a 的丈夫必須去:<a,0,b,0>、<b,1,a,1>,添邊:<a+n,b+n>,<b,a> - 若第 a 對的丈夫與第 b 對的妻子有矛盾(a b 1 0)
則 a 的丈夫去了 b 的丈夫必須去,b 的妻子去了 a 的妻子必須去:<a,1,b,1>、<b,0,a,0,>,添邊:<a,b>,<b+n,a+n> - 若第 a 對的丈夫與第 b 對的丈夫有矛盾(a b 1 1)
則 a 的丈夫去了 b 的妻子必須去,b 的丈夫去了 a 的妻子必須去:<a,1,b,0>、<b,1,a,0>,添邊:<a,b+n>,<b,a+n>
Source Program
#include<iostream> #include<cstdio> #include<cstdlib> #include<string> #include<cstring> #include<cmath> #include<ctime> #include<algorithm> #include<utility> #include<stack> #include<queue> #include<vector> #include<set> #include<map> #include<bitset> #define Exp 1e-9 #define PI acos(-1.0) #define INF 0x3f3f3f3f #define LL long long const int MOD = 1E9+7; const int N = 1000000+5; const int dx[] = {-1,1,0,0,-1,-1,1,1}; const int dy[] = {0,0,-1,1,-1,1,-1,1}; using namespace std;struct Edge{int to,next; }edge[N*2]; int head[N],tot; int n,m; int dfn[N],low[N]; bool vis[N];//標記數組 int scc[N];//記錄結點i屬于哪個強連通分量 int block_cnt;//時間戳 int sig;//記錄強連通分量個數 stack<int> S; void init(){tot=0;sig=0;block_cnt=0;memset(head,-1,sizeof(head));memset(vis,0,sizeof(vis));memset(dfn,0,sizeof(dfn));memset(low,0,sizeof(low));memset(scc,0,sizeof(scc)); } void addEdge(int from,int to){edge[++tot].to=to;edge[tot].next=head[from];head[from]=tot; } void Tarjan(int x) {vis[x]=true;dfn[x]=low[x]=++block_cnt;//每找到一個新點,紀錄當前節點的時間戳S.push(x);//當前結點入棧for(int i=head[x]; i!=-1; i=edge[i].next) { //遍歷整個棧int y=edge[i].to;//當前結點的下一結點if(!dfn[y]) {Tarjan(y);low[x]=min(low[x],low[y]);}else if(vis[y])low[x]=min(low[x],dfn[y]);}if(dfn[x]==low[x]) { //滿足強連通分量要求sig++;//記錄強連通分量個數while(true) { //記錄元素屬于第幾個強連通分量int temp=S.top();S.pop();vis[temp]=false;scc[temp]=sig;if(temp==x)break;}} } bool twoSAT(){for(int i=1;i<=2*n;i++)//找強連通分量if(!dfn[i])Tarjan(i);for(int i=1;i<=n;i++)if(scc[i]==scc[i+n])//條件a與!a屬于同一連通分量,無解return false;return true; } int main() {while( scanf("%d%d",&n,&m)!=EOF&&(n+m)){init();while(m--) {int x,y,xVal,yVal;scanf("%d%d%d%d",&x,&y,&xVal,&yVal);x++;y++;if(xVal==0&&yVal==0){//x為0或y為0addEdge(x+n,y);//x為0,y為1addEdge(y+n,x);//y為0,x為1}else if(xVal==0&&yVal==1){//x為0或y為1addEdge(x+n,y+n);//x為0,y為0addEdge(y,x);//y為1,x為1}else if(xVal==1&&yVal==0){//x為1或y為0addEdge(x,y);//x為1,y為1addEdge(y+n,x+n);//y為0,x為0}else if(xVal==1&&yVal==1){//x為1或y為1addEdge(x,y+n);//x為1,y為0addEdge(y,x+n);//y為1,x為0}}bool flag=twoSAT();if(!flag)printf("NO\n");elseprintf("YES\n");}return 0; }總結
以上是生活随笔為你收集整理的Party(HDU-3062)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: X^2 Mod P(51Nod-1014
- 下一篇: Derangement(AtCoder-