Let's go home
Time Limit: 10000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1940 Accepted Submission(s): 821
Problem Description
小时候,乡愁是一枚小小的邮票,我在这头,母亲在那头。
—— 余光中
集训是辛苦的,道路是坎坷的,休息还是必须的。经过一段时间的训练,lcy决定让大家回家放松一下,但是训练还是得照常进行,lcy想出了如下回家规定,每一个队(三人一队)或者队长留下或者其余两名队员同时留下;每一对队员,如果队员A留下,则队员B必须回家休息下,或者B留下,A回家。由于今年集训队人数突破往年同期最高记录,管理难度相当大,lcy也不知道自己的决定是否可行,所以这个难题就交给你了,呵呵,好处嘛~,免费**漂流一日。
—— 余光中
集训是辛苦的,道路是坎坷的,休息还是必须的。经过一段时间的训练,lcy决定让大家回家放松一下,但是训练还是得照常进行,lcy想出了如下回家规定,每一个队(三人一队)或者队长留下或者其余两名队员同时留下;每一对队员,如果队员A留下,则队员B必须回家休息下,或者B留下,A回家。由于今年集训队人数突破往年同期最高记录,管理难度相当大,lcy也不知道自己的决定是否可行,所以这个难题就交给你了,呵呵,好处嘛~,免费**漂流一日。
Input
第一行有两个整数,T和M,1<=T<=1000表示队伍数,1<=M<=5000表示对数。
接下来有T行,每行三个整数,表示一个队的队员编号,第一个队员就是该队队长。
然后有M行,每行两个整数,表示一对队员的编号。
每个队员只属于一个队。队员编号从0开始。
接下来有T行,每行三个整数,表示一个队的队员编号,第一个队员就是该队队长。
然后有M行,每行两个整数,表示一对队员的编号。
每个队员只属于一个队。队员编号从0开始。
Output
可行输出yes,否则输出no,以EOF为结束。
Sample Input
1 2
0 1 2
0 1
1 2
2 4
0 1 2
3 4 5
0 3
0 4
1 3
1 4
Sample Output
yes
no
题目链接:HDU 1824
2-SAT入门题目,主要是建图,每一个点$i$拆成$li$、$ri$后根据题目要求把不冲突的边连起来后求SCC,然后判断每一对拆出来的点是否在同一个SCC中即可
代码:
#include <stdio.h> #include <bits/stdc++.h> using namespace std; #define INF 0x3f3f3f3f #define LC(x) (x<<1) #define RC(x) ((x<<1)+1) #define MID(x,y) ((x+y)>>1) #define CLR(arr,val) memset(arr,val,sizeof(arr)) #define FAST_IO ios::sync_with_stdio(false);cin.tie(0); typedef pair<int, int> pii; typedef long long LL; const double PI = acos(-1.0); const int N = 1010; const int M = 5010; struct edge { int to, nxt; edge() {} edge(int _to, int _nxt): to(_to), nxt(_nxt) {} }; edge E[6 * N + 2 * M]; int head[N * 6], tot; int dfn[N * 6], low[N * 6], st[N * 6], belong[N * 6], ts, scc, top; bitset<N * 6>ins; void init() { CLR(head, -1); tot = 0; CLR(dfn, 0); CLR(low, 0); CLR(belong, 0); ts = 0; scc = 0; top = 0; ins.reset(); } inline void add(int s, int t) { E[tot] = edge(t, head[s]); head[s] = tot++; } void Tarjan(int u) { dfn[u] = low[u] = ++ts; st[top++] = u; ins[u] = 1; int i, v; for (i = head[u]; ~i; i = E[i].nxt) { v = E[i].to; if (!dfn[v]) { Tarjan(v); low[u] = min(low[u], low[v]); } else if (ins[v]) low[u] = min(low[u], dfn[v]); } if (low[u] == dfn[u]) { ++scc; do { v = st[--top]; ins[v] = 0; belong[v] = scc; } while (u != v); } } int main(void) { int n, m, a, b, c, i; while (~scanf("%d%d", &n, &m)) { init(); int gap = 3 * n; for (i = 0; i < n; ++i) //6n { scanf("%d%d%d", &a, &b, &c); add(a + gap, c); add(c + gap, a); add(a + gap, b); add(b + gap, a); add(b, c); add(c, b); } for (i = 0; i < m; ++i) //2m { scanf("%d%d", &a, &b); add(a, b + gap); add(b, a + gap); } int sz = gap << 1; for (i = 0; i < sz; ++i) if (!dfn[i]) Tarjan(i); bool flag = true; for (i = 0; i < gap; ++i) { if (belong[i] == belong[i + gap]) { flag = false; break; } } puts(flag ? "yes" : "no"); } return 0; }