HDU 1824 Let's go home 2-sat判断可行解
2016-10-06 10:47
393 查看
题目:
http://acm.hdu.edu.cn/showproblem.php?pid=1824题意:
Problem Description小时候,乡愁是一枚小小的邮票,我在这头,母亲在那头。
—— 余光中
集训是辛苦的,道路是坎坷的,休息还是必须的。经过一段时间的训练,lcy决定让大家回家放松一下,但是训练还是得照常进行,lcy想出了如下回家规定,每一个队(三人一队)或者队长留下或者其余两名队员同时留下;每一对队员,如果队员A留下,则队员B必须回家休息下,或者B留下,A回家。由于今年集训队人数突破往年同期最高记录,管理难度相当大,lcy也不知道自己的决定是否可行,所以这个难题就交给你了,呵呵,好处嘛~,免费**漂流一日。
Input
第一行有两个整数,T和M,1<=T<=1000表示队伍数,1<=M<=5000表示对数。
接下来有T行,每行三个整数,表示一个队的队员编号,第一个队员就是该队队长。
然后有M行,每行两个整数,表示一对队员的编号。
每个队员只属于一个队。队员编号从0开始。
Output
可行输出yes,否则输出no,以EOF为结束。
思路:
对于第一个条件,是要么队长留下,要么两个队员同时留下(只有一个队员留下时队长必须留下),抽象一下就是 A OR (B AND C),总结出这个后我是懵逼的,这三个布尔变量怎么搞?事实是有办法搞定的,我们建边(A’,B)(B’,A)(A’,C)(C’,A),这样建边后,A不在的话,BC必定都在,B和C有一个不在,则A必须在,这个问题就解决了。对于第二个条件,两个队员只能留下一个,这个就比较简单了,建边(A,B’)(B,A’),这样就保证两个人只有一个在。强连通缩点,如果A和A’在同一个环内,无解,否则有解总结:
数组开小了,哇了一发。。。#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <queue> using namespace std; const int N = 6010; struct edge { int to, next; } g[N*10]; int cnt, head , cnt1, head1 ; int dfn , low , scc , st , top, num, idx; bool vis ; int n, m; void add_edge(int v, int u) { g[cnt].to = u, g[cnt].next = head[v], head[v] = cnt++; } void init() { memset(head, -1, sizeof head); memset(dfn, -1, sizeof dfn); memset(vis, 0, sizeof vis); top = num = idx = cnt = 0; } void tarjan(int v) { dfn[v] = low[v] = ++idx; vis[v] = true, st[top++] = v; int u; for(int i = head[v]; i != -1; i = g[i].next) { u = g[i].to; if(dfn[u] == -1) { tarjan(u); low[v] = min(low[v], low[u]); } else if(vis[u])low[v] = min(low[v], dfn[u]); } if(dfn[v] == low[v]) { num++; do { u = st[--top]; vis[u] = false; scc[u] = num; } while(u != v); } } int main() { while(~ scanf("%d%d", &n, &m)) { init(); int v, u, w; for(int i = 1; i <= n; i++) { scanf("%d%d%d", &v, &u, &w); add_edge(v + n*3, u), add_edge(u + n*3, v); add_edge(v + n*3, w), add_edge(w + n*3, v); } for(int i = 1; i <= m; i++) { scanf("%d%d", &v, &u); add_edge(v, u + n*3), add_edge(u, v + n*3); } for(int i = 0; i < 2*3*n; i++) if(dfn[i] == -1) tarjan(i); bool flag = true; for(int i = 0; i < 3*n; i++) if(scc[i] == scc[i+3*n]) { flag = false; break; } if(flag) printf("yes\n"); else printf("no\n"); } return 0; }
相关文章推荐
- hdu 1824 Let's go home(s-sat)
- hdu 1824 Let's go home(2-sat入门)
- hdu 1824 Let's go home【2-SAT------强连通Tarjan】
- HDU 1824 Let's go home(2-sat)
- HDU 1824 Let's go home(2-SAT)
- HDU 1824 Let's go home(2-SAT)
- HDU 1824 Let's go home (2-SAT)
- HDU 1824 Let's go home (2-SAT判断)
- HDU 1824 Let's go home (2-SAT)
- HDU 1824 Let's go home (2-SAT判定)
- HDU 1824 Let's go home 2-sat基础
- HDU 1824 Let's go home(2-SAT)
- HDU-1824-Let's go home(2-SAT)
- hdu 1824 Let's go home (2-sat)
- Hdu 1824 Let's go home (2-sat 可行性判定)
- HDU 1824 —— Let's go home(2-SAT)
- HDU_1824_Let's go home(2-SAT)
- HDU - 1824 Let's go home(2-SAT)
- 【HDU】1824 Let's go home 2-sat
- HDU 1824 Let's go home 2-sat