CF1715D 题解
liangbowen · · 题解
upd 2026/5/8:以前写的傻逼产物之一,本来懒得管了,但是这个题现在怎么做的题这么多,那就撤一下了呃呃。
前言
题目传送门!
更好的阅读体验?
感觉挺不错的一道图论转化题。(其实也和图论关系不大。)
思路
对于每个条件
由于字典序最小,所以我们尽量只让
由于要表示出点与点之间的关系,我们尝试建图。对每一个条件建图:连一条
然后,枚举每一位二进制位
我们现在是看
如果
- 如果
u < v ,那么如果f_v 的第j 位没有被标记过,a_u 的第j 位才必须为1 。否则应该让a_v 为1 ,这样u 就能小一些了。 - 如果
u > v ,那么看当前a_v 的结果。如果a_v 的第j 位为0 ,那a_u 的第j 位才必须为1 。
你可能会问,
完整代码
#include <iostream>
#include <cstdio>
#define space putchar(' ')
#define endl putchar('\n')
using namespace std;
int read()
{
char op = getchar(); int x = 0, f = 1;
while (op < 48 || op > 57) {if (op == '-') f = -1; op = getchar();}
while (48 <= op && op <= 57) x = (x << 1) + (x << 3) + (op ^ 48), op = getchar();
return x * f;
}
void write(LL x)
{
if (x < 0) putchar('-'), x = -x;
if (x > 9) write(x / 10);
putchar(x % 10 + 48);
}
const int N = 1e5 + 5, M = 2e5 + 5;
struct Edge
{
int now, nxt, w;
}e[M << 1]; //这里空间要开足!赛时调了好久。
int head[N], cur;
void add(int u, int v, int w)
{
e[++cur].now = v;
e[cur].nxt = head[u];
e[cur].w = w;
head[u] = cur;
}
bool bit(int x, int j) {return x & (1 << (j - 1));} //x 的第 j 位
bool flag[N][35]; //flag[i][j]表示a[i]的第j位是否有可能为1
int a[N];
bool calc(int u, int j)
{
for (int i = head[u]; i; i = e[i].nxt)
{
int v = e[i].now, x = e[i].w;
if (!bit(x, j)) continue;
if (u < v) {if (flag[v][j]) return true;}
else {if (!bit(a[v], j)) return true;}
}
return false;
}
int main()
{
int n = read(), m = read();
for (int i = 1; i <= m; i++)
{
int u = read(), v = read(), x = read();
for (int j = 1; j <= 30; j++)
if (!bit(x, j))
flag[u][j] = flag[v][j] = true;
if (u == v) {a[u] = x; continue;} //特判,避免加边时造成自环
add(u, v, x), add(v, u, x);
}
for (int j = 1; j <= 30; j++)
for (int i = 1; i <= n; i++)
if (calc(i, j))
a[i] |= (1 << (j-1));
for (int i = 1; i <= n; i++) write(a[i]), space;
return 0;
}
希望能帮助到大家!