1241: 数字序列
Time Limit: 1 Sec Memory Limit: 128 Mb Submitted: 200 Solved: 31Description
Staginner在纸上依次写下了n个数,分别记为a1,a2,...,an,然后他给CSGrandeur提供了p条信息,现在CSGrandeur想知道,依据Staginner提供的信息,这个数列能否被唯一确定呢?
Input
输入包含若干组数据,每组数据的第一行有2个正整数,n(1<=n<=10000),p(0<=p<=20000),其中n、p的含义同上。
接下来一共有p行,每行的开头有一个字符B或S。如果为B,则B后面有3个整数i(1<=i<=n),j(1<=j<=n),k(-5000<=k<=5000),表示ai比aj大k,也即ai=aj+k;如果为S,则S后面有2个整数i(1<=i<=n),j(-5000<=j<=5000),表示ai的值为j。
Output
对于每组数据,如果根据给出的p条信息可以唯一确定出这个数列,则输出“AC”,如果p条信息可以推出矛盾,则输出“RE”,如果不能唯一确定出这个数列且p条信息并不矛盾,则输出“WA”。
Sample Input
3 3 B 2 1 1 B 3 2 1 S 2 0 2 3 B 2 1 1 S 1 0 S 2 0 3 2 B 2 1 1 B 3 2 1
Sample Output
AC RE WA
Hint
Source
CSU Monthly 2012 Feb.
用相对来统计,有点瞌睡头蒙,代码如下:
#include <cstdio>
#include <cstring>
int vis[10010],num[10010],r[10010],fa[10010];//vis表示该头目节点是否访问过 num[i]表示i作为头目节点所表示的数,但不是确切的数,相对于集体来讲的 r[i]表示i节点与头目节点的相对值 fa[i]是i的父节点
int find(int x) //压缩路径,并且使得r[i]等于i相对于根节点的值的大小
{
if(x==fa[x])
{
return x;
}
int tmp=fa[x];
fa[x]=find(fa[x]);
r[x]=r[x]+r[tmp];
return fa[x];
}
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
char op[2];
memset(vis,0,sizeof(vis));
memset(num,0,sizeof(num));
for(int i=1;i<=n;i++)
{
fa[i]=i;
r[i]=0;
}
int flag=0;
for(int i=0;i<m;i++)
{
scanf("%s",op);
if(op[0]=='B')
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
int fx=find(a);
int fy=find(b);
if(fx!=fy)//两集体合并
{
fa[fy]=fx;
r[fy]=r[a]-r[b]-c;//更新b的头目节点相对于a的头目节点的大小
if(vis[fy])//如果b的集体已经有确切的值了
{
int tmp=num[fy]-r[fy];
if(vis[fx])//如果a集体也已经有确切的值了
{
if(num[fx]!=tmp)//
{
flag=1;
}
}
else
{
num[fx]=tmp;
vis[fx]=1;
}
}
}
else//ab是一个集体中的
{
if(r[a]-r[b]!=c)
{
flag=1;
}
}
}
else
{
int a,b;
scanf("%d%d",&a,&b);
int fx=find(a);
int tmp=b-r[a];
if(vis[fx])
{
if(num[fx]!=tmp)
{
flag=1;
}
}
else
{
num[fx]=tmp;
vis[fx]=1;
}
}
}
if(flag)
{
printf("RE\n");
}
else
{
for(int i=1;i<=n;i++)
{
if(find(i)==i&&vis[i]==0)
{
flag=1;
break;
}
}
if(flag)
{
printf("WA\n");
}
else
{
printf("AC\n");
}
}
}
return 0;
}