题目大意
有一个字符串 S S S,长度为 n n n, S S S 每一个字符都是非负整数。
先给出关于 S S S 的 m m m 个信息。
每个信息包含 x , y , z x,y,z x,y,z,表示 L C P ( x , y ) = z LCP(x,y)=z LCP(x,y)=z。
请还原所有满足条件的 S S S 中,字典序最小的一个。
如果不存在这样的字符串,输出 − 1 -1 −1。
对于 100 % 100\% 100% 的数据, 1 ≤ n ≤ 1000 , 1 ≤ m ≤ 1000 1 \leq n \leq 1000,1 \leq m \leq 1000 1≤n≤1000,1≤m≤1000。
解题思路
对于每个 L C A ( x , y ) = z LCA(x,y)=z LCA(x,y)=z,肯定有 S x , x + z − 1 = S y , y + z − 1 S_{x,x+z-1}=S_{y,y+z-1} Sx,x+z−1=Sy,y+z−1,且 S x + z , x + z ≠ S y + z , y + z S_{x+z,x+z} \ne S_{y+z,y+z} Sx+z,x+z=Sy+z,y+z。
相等的关系可以用并查集维护。
再记录不相等的关系,判断是否和相等的关系相冲突。
每一个靠前的位置取小值,同一个块取相同值。
CODE
#include <bits/stdc++.h>
using namespace std;
inline int read()
{
int x = 0, f = 1;
char c = getchar();
while(c < '0' || c > '9')
{
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9')
{
x = x * 10 + c - '0';
c = getchar();
}
return x * f;
}
int n, m;
vector<int> G[1007];
int ans[1007];
bool flag;
int x[1007], y[1007], z[1007];
int fa[1007];
int vis[1007];
int find(int x)
{
return fa[x] == x ? x : fa[x] = find(fa[x]);
}
void merge(int x, int y)
{
int xx = find(x), yy = find(y);
if(xx != yy) fa[yy] = xx;
}
signed main()
{
n = read(), m = read();
for(int i = 1; i <= n; ++i) fa[i] = i;
for(int i = 1; i <= m; ++i)
{
x[i] = read(), y[i] = read(), z[i] = read();
for(int j = x[i], k = y[i], p = 1; p <= z[i]; ++p, ++j, ++k)
merge(j, k);
}
for(int i = 1; i <= m; ++i)
{
if(y[i] + z[i] > n) continue;
int xx = find(x[i] + z[i]), yy = find(y[i] + z[i]);
if(xx == yy) flag = 1;
else
{
G[xx].push_back(yy);
G[yy].push_back(xx);
}
}
if(flag)
{
puts("-1");
return 0;
}
memset(ans, -1, sizeof ans);
for(int i = 1; i <= n; ++i)
{
int a = find(i);
if(ans[a] == -1)
{
memset(vis, 0, sizeof vis);
for(int x : G[a])
if(ans[x] != -1)
vis[ans[x]] = 1;
for(int c = 0; ; ++c)
{
if (!vis[c])
{
ans[a] = c;
break;
}
}
}
ans[i] = ans[a];
}
for(int i = 1; i <= n; ++i) cout << ans[i] << " ";
cout << "\n";
return 0;
}