bzoj1728[Usaco2006 Open]Two-Headed Cows 双头牛 二分+染色
2017-06-17 16:28
761 查看
题意挺显然的就不说了。
这题我= =丢脸丢大了。。
一开始我觉得这题双头牛的模型有点像网络流,想了想反手给自己一耳光。。
然后觉得二分可做?但是怎么判断啊?
dp不可做啊,这个条件要用上的话时间会炸。
然后就蒙蔽了,想了半天没啥想法。
然后看到题解:二分+染色
第一反应:不可能啊怎么可能二分,我随手给你个反例:
4 6
1 B 3 A
1 A 3 A
2 B 3 A
2 A 3 A
4 B 3 A
4 A 3 A
1,2,4在一起,3单独一个。
然后标跑出来果然是错的,他跑出来3个。
然后我非常嗨森以为hack成功了结果被别人反手一个耳光。
可以,我脸很痛(╯‵□′)╯︵┻━┻
那这样就是道水题了。
我们直接二分,记录一下牛之间放在一起是要正向还是反向,通过连边记录,然后枚举区间左端点,二分右端点,判断的话只要dfs一下,染色的时候产生了矛盾就是不合法的。
————————————————————
UPD:二分并不是正解,是萎的。。。根据Claris大爷的说法,可以构造数据让你二分每次都fail,然后你的复杂度就是nm的了。
正解是倍增,找到一个最大的k满足l+2^k合法 但是l+2^(k+1)不合法
我倒是觉得2-SAT可以做,感觉模型特别像啊,而且要是O(m)的话岂不是很zici?我先去写一下。
这题我= =丢脸丢大了。。
一开始我觉得这题双头牛的模型有点像网络流,想了想反手给自己一耳光。。
然后觉得二分可做?但是怎么判断啊?
dp不可做啊,这个条件要用上的话时间会炸。
然后就蒙蔽了,想了半天没啥想法。
然后看到题解:二分+染色
第一反应:不可能啊怎么可能二分,我随手给你个反例:
4 6
1 B 3 A
1 A 3 A
2 B 3 A
2 A 3 A
4 B 3 A
4 A 3 A
1,2,4在一起,3单独一个。
然后标跑出来果然是错的,他跑出来3个。
然后我非常嗨森以为hack成功了结果被别人反手一个耳光。
可以,我脸很痛(╯‵□′)╯︵┻━┻
那这样就是道水题了。
我们直接二分,记录一下牛之间放在一起是要正向还是反向,通过连边记录,然后枚举区间左端点,二分右端点,判断的话只要dfs一下,染色的时候产生了矛盾就是不合法的。
————————————————————
UPD:二分并不是正解,是萎的。。。根据Claris大爷的说法,可以构造数据让你二分每次都fail,然后你的复杂度就是nm的了。
正解是倍增,找到一个最大的k满足l+2^k合法 但是l+2^(k+1)不合法
我倒是觉得2-SAT可以做,感觉模型特别像啊,而且要是O(m)的话岂不是很zici?我先去写一下。
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<cmath> #define fo(i,a,b) for(int i=a;i<=b;i++) #define fd(i,a,b) for(int i=a;i>=b;i--) using namespace std; int n, m; const int N = 1e5 + 5; int read() { int x = 0, f = 1; char ch = getchar(); while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); } while (ch >= '0'&&ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); } return x*f; } int head , go , next , val ; int col , vis , tot; char s1[5], s2[5]; inline void add(int x, int y, int z) { go[++tot] = y; next[tot] = head[x]; val[tot] = z; head[x] = tot; } bool dfs(int x, int l, int r) { vis[x] = 1; bool ans = 1; for (int i = head[x]; i; i = next[i]) { int v = go[i]; if (v < l||v > r)continue; if (vis[v]) { if ((col[x] ^ val[i]) != col[v])ans = 0; continue; } col[v] = col[x] ^ val[i]; ans = ans&&dfs(v, l, r); } return ans; } bool pd(int l, int r) { bool flag = 1; fo(i, l, r)vis[i] = 0, col[i] = -1; col[l] = 0; fo(i, l, r)if (!vis[i])flag = flag&&dfs(i, l, r); return flag; } int main() { n = read(), m = read(); fo(i, 1, m) { int x, y; x = read(); scanf("%s", s1); y = read(); scanf("%s", s2); if (x == y)continue; if (s1[0] == s2[0]) { add(x, y, 1); add(y, x, 1); } else { add(x, y, 0); add(y, x, 0); } } int ans = 0; fo(i, 1, n) { int l = i, r = n; while (r - l > 1) { int mid = (l + r) >> 1; if (pd(i, mid))l = mid; else r = mid; } if (pd(i, r))l = r; i = l, ans++; } printf("%d\n", ans); }
相关文章推荐
- bzoj1664 [Usaco2006 Open]County Fair Events 参加节日庆祝
- 【动态规划】bzoj1664 [Usaco2006 Open]County Fair Events 参加节日庆祝
- 【BZOJ】1665: [Usaco2006 Open]The Climbing Wall 攀岩(spfa)
- |BZOJ 1650|二分|贪心|[Usaco2006 Dec]River Hopscotch 跳石子
- 【bzoj1727】[Usaco2006 Open]The Milk Queue 挤奶队列 贪心
- BZOJ 1664 [Usaco2006 Open]County Fair Events 参加节日庆祝 贪心
- 【bzoj1663】[Usaco2006 Open]赶集 dp
- BZOJ 1663: [Usaco2006 Open]赶集 floyd(划掉+dp
- bzoj:1665 [Usaco2006 Open]The Climbing Wall 攀岩
- 【动态规划】bzoj1663 [Usaco2006 Open]赶集
- BZOJ1727: [Usaco2006 Open]The Milk Queue 挤奶队列
- bzoj1727 [Usaco2006 Open]The Milk Queue 挤奶队列 贪心
- bzoj 1663: [Usaco2006 Open]赶集(最长路)
- 【BZOJ】1650: [Usaco2006 Dec]River Hopscotch 跳石子(二分+贪心)
- bzoj 1664: [Usaco2006 Open]County Fair Events 参加节日庆祝(DP)
- BZOJ 1717: [Usaco2006 Dec]Milk Patterns 产奶的模式 二分答案 哈希/后缀数组
- [BZOJ]1717 [Usaco2006 Dec]Milk Patterns 二分答案
- bzoj1650: [Usaco2006 Dec]River Hopscotch 跳石子 luogu【P2678】 跳石头 (二分)
- [BZOJ1663] [Usaco2006 Open]赶集(spfa最长路)
- bzoj 1720: [Usaco2006 Jan]Corral the Cows 奶牛围栏 二分