有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
对于(a,a'),(b,b'),如果a,b构成仇恨关系,那么如果选a,则必须选b',选b则必须选a',建边a->b',b->a'表示必须关系,也就是说如果选了连通分量里的一个点,那么其余所有边都必须选,则本体a,a'在一个连通分量里为非法,只需要判断就好啦。。。
#pragma GCC optimize(2) #include<stdio.h> #include<algorithm> #include<string.h> #include<set> #include<vector> #include<queue> using namespace std; const int maxn = 1e6 + 100; const int inf = 0x3f3f3f3f; typedef long long ll; struct node { int v, next; }edge[maxn]; int head[maxn], dfn[maxn], low[maxn], instack[maxn], Stack[maxn], belong[maxn]; int n, tot, index, top, cnt; void init() { memset(head, -1, sizeof(head)); memset(dfn, 0, sizeof(dfn)); tot = index = 0; } void addedge(int u, int v) { edge[tot].v = v; edge[tot].next = head[u]; head[u] = tot++; return; } void tarjan(int u) { dfn[u] = low[u] = ++index; instack[u] = 1; Stack[top++] = u; for (int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].v; if (!dfn[v]) { tarjan(v); low[u] = min(low[u], low[v]); } else if (instack[v]) { low[u] = min(low[u], dfn[v]); } } if (low[u] == dfn[u]) { cnt++; int v; do { v = Stack[--top]; instack[v] = 0; belong[v] = cnt; } while (u != v); } } int main() { //freopen("C://input.txt", "r", stdin); while (scanf("%d", &n) != EOF) { init(); top = 0; cnt = 0; int m; scanf("%d", &m); for (int i = 0; i < m; i++) { int a, b, c, d; scanf("%d%d%d%d", &a, &b, &c, &d); a = (a << 1) + c; b = (b << 1) + d; addedge(a, b ^ 1); addedge(b, a ^ 1); } for (int i = 0; i < n << 1; i++) { if (!dfn[i]) { tarjan(i); } } int flag = 0; for (int i = 0; i < n ; i++) { if (belong[i << 1] == belong[(i << 1) ^ 1]) { flag = 1; } } if (flag) { printf("NO\n"); } else { printf("YES\n"); } } return 0; }
hdu 3062 Party (2-sat 基础题)
最新推荐文章于 2020-12-18 21:18:57 发布