4013: [HNOI2015]实验比较
Time Limit: 5 Sec Memory Limit: 512 MBSubmit: 535 Solved: 268
[ Submit][ Status][ Discuss]
Description
小
D
被邀请到实验室,做一个跟图片质量评价相关的主观实验。实验用到的图片集一共有
N
张图片,编号为
1
到
N
。实验分若干轮进行,在每轮实验中,小
D
会被要求观看某两张随机选取的图片,
然后小
D
需要根据他自己主观上的判断确定这两张图片谁好谁坏,或者这两张图片质量差不多。
用符号“
<
”、“
>
”和“
=
”表示图片
x
和
y
(
x
、
y
为图片编号)之间的比较:如果上下文中
x
和
y
是图片编号,则
x<y
表示图片
x
“质量优于”
y
,
x>y
表示图片
x
“质量差于”
y
,
x=y
表示图片
x
和
y
“质量相同”;也就是说,这种上下文中,“
<
”、“
>
”、“
=
”分别是质量优于、质量差于、质量相同的意思;在其他上下文中,这三个符号分别是小于、大于、等于的含义。图片质量比较的推理规则(在
x
和
y
是图片编号的上下文中):(
1
)
x < y
等价于
y > x
。(
2
)若
x < y
且
y = z
,则
x < z
。(
3
)若
x < y
且
x = z
,则
z < y
。(
4
)
x=y
等价于
y=x
。(
5
)若
x=y
且
y=z
,则
x=z
。
实验中,小
D
需要对一些图片对
(x, y)
,给出
x < y
或
x = y
或
x > y
的主观判断。小
D
在做完实验后,
忽然对这个基于局部比较的实验的一些全局性质产生了兴趣。在主观实验数据给定的情形下,定义这
N
张图片的一个合法质量序列为形如“
x1 R1 x2 R2 x3 R3
…
xN-1 RN-1 xN
”的串,也可看作是集合
{ xi Ri xi+1|1<=i<=N-1}
,其中
xi
为图片编号,
x1,x2,
…
,xN
两两互不相同(即不存在重复编号),
Ri
为
<
或
=
,“合法”是指这个图片质量序列与任何一对主观实验给出的判断不冲突。
例如:
质量序列
3 < 1 = 2
与主观判断“
3 > 1
,
3 = 2”冲突(因为质量序列中 3<1
且
1=2
,从而
3<2
,这与主观判断中的
3=2
冲突;同时质量序列中的
3<1
与主观判断中的
3>1
冲突)
,但与主观判断“
2 = 1
,
3 < 2”
不冲突;因此给定主观判断“
3>1
,
3=2”时,1<3=2
和
1<2=3
都是合法的质量序列,
3<1=2
和
1<2<3
都是非法的质量序列。由于实验已经做完一段时间了,小
D
已经忘了一部分主观实验的数据。对每张图片
i
,小
D
都最多只记住了某一张质量不比
i
差的另一张图片
Ki
。这些小
D
仍然记得的质量判断一共有
M
条(
0 <= M <= N
),其中第
i
条涉及的图片对为
(KXi, Xi)
,判断要么是
KXi < Xi
,要么是
KXi = Xi
,而且所有的
Xi
互不相同。小
D
打算就以这
M
条自己还记得的质量判断作为他的所有主观数据。现在,基于这些主观数据,我们希望你帮小
D
求出这
N
张图片一共有多少个不同的合法质量序列。我们规定:
如果质量序列中出现“
x = y
”,那么序列中交换
x
和
y
的位置后仍是同一个序列。
因此:
1<2=3=4<5
和
1<4=2=3<5
是同一个序列,
1 < 2 = 3
和
1 < 3 = 2
是同一个序列,而
1 < 2 < 3
与
1 < 2 = 3
是不同的序列,
1<2<3
和
2<1<3
是不同的序列。
由于合法的图片质量序列可能很多,
所以你需要输出答案对
10^9 + 7
取模的结果
Input
第一行两个正整数N,M,分别代表图片总数和小D仍然记得的判断的条数;
接下来M行,每行一条判断,每条判断形如”x < y”或者”x = y”。
Output
输出仅一行,包含一个正整数,表示合法质量序列的数目对 10^9+7取模的结果。
Sample Input
5 4
1 < 2
1 < 3
2 < 4
1 = 5
1 < 2
1 < 3
2 < 4
1 = 5
Sample Output
5
HINT
不同的合法序列共5个,如下所示:
1 = 5 < 2 < 3 < 4
1 = 5 < 2 < 4 < 3
1 = 5 < 2 < 3 = 4
1 = 5 < 3 < 2 < 4
1 = 5 < 2 = 3 < 4
100%的数据满足N<=100。
Source
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
const int maxn = 111;
typedef long long LL;
const LL mo = 1000000007;
const char D[3] = {'<','=','>'};
int n,m,fa[maxn],du[maxn],siz[maxn],f[maxn][maxn],h[maxn],C[maxn][maxn];
bool G[maxn][maxn],vis[maxn];
vector <int> v[maxn],g[maxn];
queue <int> Q;
int Mul(const LL &x,const LL &y) {return x * y % mo;}
int Add(const int &x,const int &y) {return (x + y) % mo;}
int getfa(int k) {return k == fa[k] ? k : fa[k] = getfa(fa[k]);}
int Read()
{
char ch = getchar();
while (ch != '<' && ch != '=' && ch != '>') ch = getchar();
for (int i = 0; ; i++) if (ch == D[i]) return i;
}
int getint()
{
char ch = getchar(); int ret = 0;
while (ch < '0' || '9' < ch) ch = getchar();
while ('0' <= ch && ch <= '9')
ret = ret * 10 + ch - '0',ch = getchar();
return ret;
}
void Dfs(int x)
{
siz[x] = f[x][1] = 1;
for (int I = 0; I < v[x].size(); I++)
{
int y = v[x][I]; Dfs(y);
for (int i = 0; i < siz[x]; i++)
for (int j = 1; j <= siz[y]; j++)
for (int k = max(i,j); k <= i + j; k++)
{
int A = Mul(f[x][i+1],f[y][j]);
int B = Mul(C[k][i],C[i][j-k+i]);
h[k+1] = Add(h[k+1],Mul(A,B));
}
memcpy(f[x],h,sizeof(h)); memset(h,0,sizeof(h)); siz[x] += siz[y];
}
}
int main()
{
#ifdef DMC
freopen("DMC.txt","r",stdin);
#endif
n = getint(); m = getint(); C[0][0] = 1;
for (int i = 1; i <= n; i++)
{
C[i][0] = 1;
for (int j = 1; j <= i; j++)
C[i][j] = Add(C[i-1][j],C[i-1][j-1]);
}
for (int i = 1; i <= n; i++) fa[i] = i;
while (m--)
{
int x = getint(),typ,y;
typ = Read(); y = getint();
if (!typ) g[x].push_back(y);
else if (typ == 2) g[y].push_back(x);
else
{
int fx = getfa(x),fy = getfa(y);
if (fx != fy) fa[fx] = fy;
}
}
for (int i = 1; i <= n; i++)
{
int x = getfa(i);
for (int j = 0; j < g[i].size(); j++)
{
int y = getfa(g[i][j]);
if (!G[x][y]) v[x].push_back(y),++du[y],G[x][y] = 1;
}
}
for (int i = 1; i <= n; i++)
if (!du[i] && fa[i] == i) ++du[i],v[0].push_back(i);
Q.push(0);
while (!Q.empty())
{
int k = Q.front(); Q.pop(); vis[k] = 1;
for (int i = 0; i < v[k].size(); i++)
{
int to = v[k][i]; --du[to];
if (!du[to]) Q.push(to);
}
}
for (int i = 1; i <= n; i++) if (!vis[i] && fa[i] == i) {puts("0"); return 0;}
Dfs(0); int Ans = 0;
for (int i = 1; i <= siz[0]; i++) Ans = Add(Ans,f[0][i]);
cout << Ans << endl;
return 0;
}