您的位置:首页 > 运维架构

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?我先去写一下。

#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);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: