Description
在实验室中, Nathan Wada 作为助手的职责是测定两个样品的重量差异。当样品的差异很小时,使用天平能比使用弹簧秤得到更精确的结果,所以他只使用天平来测得一些样品的重量差。他偶尔会被询问一些样品的重量差,而他能否回答这些问题取决于在回答相应问题时他已经得到的测量结果。由于他所在处理的测量数据是巨大的,所以他希望你能写个程序帮他处理数据和回答问题。
Input
输入包含多组测试数据。每组数据第一行包含两个整数
N
和
接下来
M
行,每行包括一个测量结果或者询问,按时间顺序给出,满足
一个测量结果被格式化为
!
满足
一个询问被格式化为
?
输入以两个零作为结束。
Output
对于每个询问输出一行,如果能回答问题,则输出问题的答案,你可以认为答案的绝对值不超过 1000000 否则输出 UNKNOWN ,表示不能回答问题。
Solution
带权并查集,用带权边表示一个物品和它父亲的重量关系,路径压缩时要压缩边权
#include<stdio.h>
#include<algorithm>
#include<cstring>
#define N 100001
using namespace std;
int n,m,u,v,f[N],c[N],w;
char ch;
void gf(const int &a)
{
if (f[a]==a) return;
else
{
gf(f[a]);
c[a]+=c[f[a]];
f[a]=f[f[a]];
}
}
int main()
{
while (1)
{
scanf("%d%d",&n,&m);
if (n==0) return 0;
for (int i=1;i<=n;i++) f[i]=i;
memset(c,0,sizeof(c));
while (m--)
{
for (ch=getchar();ch!='!' && ch!='?';ch=getchar());
scanf("%d%d",&u,&v);gf(u),gf(v);
if (ch=='!')
{
scanf("%d",&w);
if (f[u]==f[v]) continue;
c[f[u]]=w-c[u]+c[v];
f[f[u]]=f[v];
}
else if (f[u]==f[v] && abs(c[u]-c[v])<=1000000) printf("%d\n",c[u]-c[v]);
else puts("UNKNOWN");
}
}
}