[SPOJ839]Optimal Marks

试题描述

You are given an undirected graph \(G(V, E)\). Each vertex has a mark which is an integer from the range \([0..2^{31} - 1]\). Different vertexes may have the same mark.

For an edge \((u, v)\), we define \(Cost(u, v) = mark[u] xor mark[v]\).

Now we know the marks of some certain nodes. You have to determine the marks of other nodes so that the total cost of edges is as small as possible.

给你一个无向图,有些点权值固定,你需要个剩下的点确定权值使得所有边的权值之和最小。边权定义为它连接的两个点的点权异或。

输入

The first line of the input data contains integer \(T\) \((1 \le T \le 10)\) - the number of testcases. Then the descriptions of \(T\) testcases follow.

First line of each testcase contains \(2\) integers \(N\) and \(M\) \((0 < N \le 500, 0 \le M \le 3000)\). \(N\) is the number of vertexes and \(M\) is the number of edges. Then \(M\) lines describing edges follow, each of them contains two integers \(u, v\) representing an edge connecting \(u\) and \(v\).

Then an integer \(K\), representing the number of nodes whose mark is known. The next \(K\) lines contain \(2\) integers \(u\) and \(p\) each, meaning that node \(u\) has a mark \(p\). It’s guaranteed that nodes won’t duplicate in this part.

输出

For each testcase you should print \(N\) lines integer the output. The \(K\)th line contains an integer number representing the mark of node \(K\). If there are several solutions, you have to output the one which minimize the sum of marks. If there are several solutions, just output any of them.

输入示例

  1. 1
  2. 3 2
  3. 1 2
  4. 2 3
  5. 2
  6. 1 5
  7. 3 100

输出示例

  1. 5
  2. 4
  3. 100

数据规模及约定

见“输入

题解

异或、求和,每一位都互不影响,套路做法就是按位处理。

对于某一位,每个点的点权只有 \(0/1\) 两种情况,自然想到 \(0\) 的点属于 \(S\) 割,\(1\) 的点属于 \(T\) 割,然后把原图复制上去,无向边边权为 \(1\),跑最小割。

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cstring>
  5. #include <cctype>
  6. #include <algorithm>
  7. using namespace std;
  8. #define rep(i, s, t) for(int i = (s); i <= (t); i++)
  9. #define dwn(i, s, t) for(int i = (s); i >= (t); i--)
  10. int read() {
  11. int x = 0, f = 1; char c = getchar();
  12. while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
  13. while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
  14. return x * f;
  15. }
  16. #define maxn 510
  17. #define maxm 7010
  18. #define oo 2147483647
  19. struct Edge {
  20. int from, to, flow;
  21. Edge() {}
  22. Edge(int _1, int _2, int _3): from(_1), to(_2), flow(_3) {}
  23. };
  24. struct Dinic {
  25. int n, m, s, t, head[maxn], nxt[maxm];
  26. Edge es[maxm];
  27. int vis[maxn], Q[maxn], hd, tl;
  28. int cur[maxn];
  29. bool tcut[maxn];
  30. void init() {
  31. m = 0; memset(head, -1, sizeof(head));
  32. return ;
  33. }
  34. void setn(int _) {
  35. n = _;
  36. return ;
  37. }
  38. void AddEdge(int a, int b, int c) {
  39. es[m] = Edge(a, b, c); nxt[m] = head[a]; head[a] = m++;
  40. return ;
  41. }
  42. bool BFS() {
  43. memset(vis, 0, sizeof(vis));
  44. hd = tl = 0; Q[++tl] = t;
  45. vis[t] = 1;
  46. while(hd < tl) {
  47. int u = Q[++hd];
  48. for(int i = head[u]; i != -1; i = nxt[i]) {
  49. Edge& e = es[i^1];
  50. if(!vis[e.from] && e.flow) {
  51. vis[e.from] = vis[u] + 1;
  52. Q[++tl] = e.from;
  53. }
  54. }
  55. }
  56. return vis[s] > 0;
  57. }
  58. int DFS(int u, int a) {
  59. if(u == t || !a) return a;
  60. int flow = 0, f;
  61. for(int& i = cur[u]; i != -1; i = nxt[i]) {
  62. Edge& e = es[i];
  63. if(vis[e.to] == vis[u] - 1 && (f = DFS(e.to, min(a, e.flow)))) {
  64. flow += f; a -= f;
  65. e.flow -= f; es[i^1].flow += f;
  66. if(!a) return flow;
  67. }
  68. }
  69. return flow;
  70. }
  71. int MaxFlow(int _s, int _t) {
  72. s = _s; t = _t;
  73. int flow = 0;
  74. while(BFS()) {
  75. rep(i, 1, n) cur[i] = head[i];
  76. flow += DFS(s, oo);
  77. }
  78. return flow;
  79. }
  80. void dfs(int u) {
  81. if(tcut[u]) return ;
  82. tcut[u] = 1;
  83. for(int i = head[u]; i != -1; i = nxt[i]) {
  84. Edge& e = es[i^1];
  85. if(e.flow) dfs(e.from);
  86. }
  87. return ;
  88. }
  89. } sol;
  90. #define pii pair <int, int>
  91. #define x first
  92. #define y second
  93. #define mp(x, y) make_pair(x, y)
  94. pii es[maxm];
  95. int n, m, val[maxn], getv[maxn];
  96. void solve(int bit) {
  97. int s = n + 1, t = n + 2;
  98. sol.init(); sol.setn(t);
  99. rep(i, 1, m) sol.AddEdge(es[i].x, es[i].y, 1), sol.AddEdge(es[i].y, es[i].x, 1);
  100. rep(i, 1, n) if(val[i] >= 0) {
  101. if(val[i] >> bit & 1) sol.AddEdge(i, t, oo), sol.AddEdge(t, i, 0);
  102. else sol.AddEdge(s, i, oo), sol.AddEdge(i, s, 0);
  103. }
  104. sol.MaxFlow(s, t);
  105. memset(sol.tcut, 0, sizeof(sol.tcut));
  106. sol.dfs(t);
  107. rep(i, 1, n) if(val[i] < 0)
  108. getv[i] |= sol.tcut[i] << bit;
  109. return ;
  110. }
  111. int main() {
  112. int T = read();
  113. while(T--) {
  114. n = read(); m = read();
  115. memset(val, -1, sizeof(val));
  116. rep(i, 1, m) {
  117. int a = read(), b = read();
  118. es[i] = mp(a, b);
  119. }
  120. int k = read();
  121. rep(i, 1, k) {
  122. int t = read();
  123. val[t] = read();
  124. }
  125. memset(getv, 0, sizeof(getv));
  126. rep(i, 0, 31) solve(i);
  127. rep(i, 1, n) if(val[i] >= 0) printf("%d\n", val[i]); else printf("%d\n", getv[i]);
  128. }
  129. return 0;
  130. }

大概这题数据范围有问题,二进制位从 \(0\) 到 \(30\) 就 WA,到 \(31\) 就 A 了。

[SPOJ839]Optimal Marks的更多相关文章

  1. SPOJ839 Optimal Marks(最小割)

    题目大概说给一张图,每个点都有权,边的权等于其两端点权的异或和,现已知几个点的权,为了使所有边的边权和最小,其他点的权值该是多少. 很有意思的一道题,完全看不出和网络流有什么关系. 考虑每个未知的点$ ...

  2. spoj839 Optimal Marks(最小割,dinic)

    题目大意: 给你一个无向图\(G(V,E)\). 每个顶点都有一个int范围内的整数的标记. 不同的顶点可能有相同的标记. 对于边\((u,v)\),我们定义\(Cost(u,v)=mark [u]\ ...

  3. 图论(网络流):SPOJ OPTM - Optimal Marks

    OPTM - Optimal Marks You are given an undirected graph G(V, E). Each vertex has a mark which is an i ...

  4. SPOJ OPTM - Optimal Marks

    OPTM - Optimal Marks no tags  You are given an undirected graph G(V, E). Each vertex has a mark whic ...

  5. SP839 Optimal marks(最小割)

    SP839 Optimal marks(最小割) 给你一个无向图G(V,E). 每个顶点都有一个int范围内的整数的标记. 不同的顶点可能有相同的标记.对于边(u,v),我们定义Cost(u,v)= ...

  6. Optimal Marks(optimal)

    Optimal Marks(optimal) 题目描述 定义无向图边的值为这条边连接的两个点的点权异或值. 定义无向图的值为无向图中所有边的值的和. 给定nn个点mm条边构成的图.其中有些点的权值是给 ...

  7. 【bzoj2400】Spoj 839 Optimal Marks 按位最大流

    Spoj 839 Optimal Marks Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 908  Solved: 347[Submit][Stat ...

  8. 【BZOJ2400】Spoj 839 Optimal Marks 最小割

    [BZOJ2400]Spoj 839 Optimal Marks Description 定义无向图中的一条边的值为:这条边连接的两个点的值的异或值. 定义一个无向图的值为:这个无向图所有边的值的和. ...

  9. SPOJ839 OPTM - Optimal Marks

    传送门 闵神讲网络流应用的例题,来水一水 要写出这道题,需要深入理解两个概念,异或和最小割. 异或具有相对独立性,所以我们把每一位拆开来看,即做大概$32$次最小割.然后累加即可. 然后是最小割把一张 ...

随机推荐

  1. Flutter /bin/sh: /packages/flutter_tools/bin/xcode_backend.sh: No such file or directory

    自己写项目中遇到的一个问题, 可以出来是路径找不到,应该是FLUTTER_ROOT这个全局变量没有取到值的原因 1.检查xcode_backend.sh 是否真的存在 2.网上说的:Target -& ...

  2. C#事件与接口编程实例

    很多初学c#的朋友对于事件与接口感到迷惑不解,不明白它们之间的关系,下面我就用实例来简单的分析讲解一下. 事件,用event修饰符来代表一个事件,我们要创建一个C#事件必须按以下顺序来扫行: 1,创建 ...

  3. 国产中标麒麟Linux部署dotnet core 环境并运行项目 (三) 部署运行WEB API项目

    部署dotnet Core Web API 上一步的文章,是我们公司最核心的一个ORM组件,在中标麒麟系统完成了一个插入数据的任务,这一步是将正式的从dot net framework 迁移到 dot ...

  4. Oracle 汇总函数

    汇总函数,也叫统计函数.聚合函数.分组函数 汇总函数必须跟 group by 语句一起使用,对数据进行分组汇总. ① 求和:sum(col).列必须是数值. ② 最小值:min(col).列可以是数值 ...

  5. 【C++学习笔记】 链式前向星

    链式前向星是一种常见的储存图的方式(是前向星存图法的优化版本),支持增边和查询,但不支持删边(如果想要删除指定的边建议用邻接矩阵). 储存方式 首先定义数组 head[ i ] 来储存从节点 i 出发 ...

  6. elasticsearch 7 安装

    elasticsearch 安装 操作系统:CentOS Linux release 7.4 elasticsearch:elasticsearch-7.1.1 es7+centos7 1.软件下载 ...

  7. redis 设置密码验证

    1.找到配置文件:如/etc/redis/redis.conf 2.找到以下内容 # requirepass foobared 3.修改为(redispassword是密码) requirepass ...

  8. HTTP 配置与编译安装

    目录 HTTP 配置与编译安装 HTTP 相关配置 DSO 定义'Main' Server 的文档页面路径 定义站点主页面 站点访问控制常见机制 基于源地址实现访问控制 日志设定 设定默认字符集 定义 ...

  9. python笔记-dict字典的方法

    #!/usr/bin/env python #-*- coding:utf-8 -*- #打印0001-9999的数字 for i in range(9999): s = "%04d&quo ...

  10. 利用python生成图形验证码

    validCode.py import random from io import BytesIO from PIL import Image, ImageDraw, ImageFont def ge ...