传送门

论文《最小割模型在信息学竞赛中的应用》原题

二进制不同位上互不影响,那么就按位跑网络流

每一位上,确定的点值为1的与S连一条容量为INF的有向边。为0的与T连一条容量为INF的有向边。

其他的按给定的无向图建边,容量为1。

统计答案是从源点能到达的点(流量未达到容量)即为该位上为1的点。

需要跑多少遍根据所有权值的最高位来确定。直接跑30次TLE了。

#include <bits/stdc++.h>
using namespace std; inline int read() {
int x = , f = ; char ch = getchar();
while (ch < '' || ch > '') { if (ch == '-') f = -; ch = getchar(); }
while (ch >= '' && ch <= '') { x = x * + ch - ; ch = getchar(); }
return x * f;
} const int INF = 0x3f3f3f3f;
const int N = 2e5 + ;
struct Edge { int v, next, f; } edge[N];
struct IN { int u, v; } in[N];
int head[N], cnt, level[N], iter[N], n, m;
int a[N], res[N];
bool vis[N];
vector<int> appear; inline void add(int u, int v, int f) {
edge[cnt].v = v; edge[cnt].f = f; edge[cnt].next = head[u]; head[u] = cnt++;
} bool bfs(int s, int t) {
for (int i = ; i <= t; i++) level[i] = -, iter[i] = head[i];
queue<int> que;
que.push(s);
level[s] = ;
while (!que.empty()) {
int u = que.front(); que.pop();
for (int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].v, f = edge[i].f;
if (level[v] < && f) {
que.push(v);
level[v] = level[u] + ;
}
}
}
return level[t] != -;
} int dfs(int u, int t, int f) {
if (u == t || !f) return f;
int flow = ;
for (int i = iter[u]; ~i; i = edge[i].next) {
iter[u] = i;
int v = edge[i].v;
if (level[v] == level[u] + && edge[i].f) {
int w = dfs(v, t, min(f, edge[i].f));
if (!w) continue;
flow += w; f -= w;
edge[i].f -= w; edge[i^].f += w;
if (f <= ) break;
}
}
return flow;
} int dinic(int s, int t) {
int ans = ;
while (bfs(s, t)) ans += dfs(s, t, INF);
return ans;
} void get_ans(int u, int bit) {
vis[u] = ;
res[u] += << bit;
for (int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].v;
if (!vis[v] && edge[i].f) {
get_ans(v, bit);
}
}
} void solve(int bit, int s, int t) {
for (int i = ; i <= t; i++) head[i] = -, vis[i] = false;
cnt = ;
for (int i = , sz = appear.size(); i < sz; i++) {
int x = appear[i];
if (( << bit) & a[x]) {
add(s, x, INF);
add(x, s, );
} else {
add(x, t, INF);
add(t, x, );
}
}
for (int i = ; i <= m; i++) { add(in[i].u, in[i].v, ); add(in[i].v, in[i].u, ); }
dinic(s, t);
get_ans(s, bit);
} inline void init() {
for (int i = ; i <= n; i++) {
res[i] = a[i] = ;
}
appear.clear();
} int main() {
int T = read();
while (T--) {
n = read(), m = read();
init();
int s = , t = n + ;
int mak = ;
for (int i = ; i <= m; i++) {
in[i].u = read(), in[i].v = read();
}
int k = read();
while (k--) {
int u = read();
a[u] = read();
appear.emplace_back(u);
}
for (int i = , sz = appear.size(); i < sz; i++) {
int u = appear[i];
int temp = a[u];
int bit = ;
while (temp) {
bit++;
temp >>= ;
}
mak = max(bit, mak);
}
for (int i = ; i <= mak; i++) {
solve(i, s, t);
}
for (int i = ; i <= n; i++) printf("%d\n", res[i]);
}
}

Optimal Marks SPOJ - OPTM(最小割)的更多相关文章

  1. Optimal Marks SPOJ - OPTM (按位枚举-最小割)

    题意:给一张无向图,每个点有其点权,边(i,j)的cost是\(val_i\ XOR \ val_j\).现在只给出K个点的权值,求如何安排其余的点,使总花费最小. 分析:题目保证权值不超过32位整型 ...

  2. BZOJ 2400: Spoj 839 Optimal Marks (按位最小割)

    题面 一个无向图,一些点有固定权值,另外的点权值由你来定. 边的值为两点的异或值,一个无向图的值定义为所有边的值之和. 求无向图的最小值 分析 每一位都互不干扰,按位处理. 用最小割算最小值 保留原图 ...

  3. Optimal Marks SPOJ - OPTM

    传送门 一个无向图,每个点有点权,某些点点权确定了,某些点由你来确定,边权为两个点的异或和,要使边权和最小. 这不是一道按位做最小割的大水题么 非常开心地打了,还非常开心地以为有spj,然后非常开心地 ...

  4. Luogu SP839 OPTM - Optimal Marks(按位最小割)

    这道题和 BZOJ 2400 是一道题,不多讲了 CODE #include <cstdio> #include <cstring> #include <vector&g ...

  5. 839. Optimal Marks - SPOJ

    You are given an undirected graph G(V, E). Each vertex has a mark which is an integer from the range ...

  6. Optimal Marks SPOJ 839

    这题远超其他题非常靠近最小割的实际意义: 割边<=>付出代价<=>决定让两个点的值不相同,边权增加 最小割<=>点的值与s一个阵营的与s相同,与t一个阵营的与t相同 ...

  7. spoj 839 最小割+二进制

    #include<stdio.h> #include<string.h> #include<queue> using namespace std; #define ...

  8. SPOJ 839 OPTM - Optimal Marks (最小割)(权值扩大,灵活应用除和取模)

    http://www.spoj.com/problems/OPTM/ 题意: 给出一张图,点有点权,边有边权 定义一条边的权值为其连接两点的异或和 定义一张图的权值为所有边的权值之和 已知部分点的点权 ...

  9. spoj 839 OPTM - Optimal Marks&&bzoj 2400【最小割】

    因为是异或运算,所以考虑对每一位操作.对于所有已知mark的点,mark的当前位为1则连接(s,i,inf),否则连(i,t,inf),然后其他的边按照原图连(u,v,1),(v,u,1),跑最大流求 ...

随机推荐

  1. vue 项目不显示样式 排版错乱

    vue中的css 样式都在index.html中 看这里是否有导入css

  2. 用Scratch制作一个Hello World程序

    网上出现了很多Hello World程序,看的小编心里也痒痒的,为此这次作为南京小码王Scratch培训机构的小编,就为大家来详细的了解下Scratch制作Hello World程序的过程,现在就和小 ...

  3. Kubernetes(K8s)基础知识(docker容器技术)

    今天谈谈K8s基础知识关键词: 一个目标:容器操作:两地三中心:四层服务发现:五种Pod共享资源:六个CNI常用插件:七层负载均衡:八种隔离维度:九个网络模型原则:十类IP地址:百级产品线:千级物理机 ...

  4. selenium中的元素操作之三大等待(一)

    等待时做什么,为什么使用等待 在做自动化测试,设计测试用例的时候,有时下一步的操作会依赖上一步的结果或者内容,上一步操作成功之后才能进行下一步操作等,这时候,我们就需要使用等待,来判断上一步操作是否完 ...

  5. 单IP、网络、别名管道限速的设置

    单IP.网络.别名管道限速的设置 在设备上,控制网络限速最常用的是流量×××中的“限制器”,你可以把它理解为一个管道,20Mit/s的下载管道,那么下载的最大流量就不会超过20Mit/s.流量限制器结 ...

  6. 2019 拼多多java面试笔试题 (含面试题解析)

    本人3年开发经验.18年年底开始跑路找工作,在互联网寒冬下成功拿到阿里巴巴.今日头条.拼多多等公司offer,岗位是Java后端开发,最终选择去了拼多多. 面试了很多家公司,感觉大部分公司考察的点都差 ...

  7. 2019-07-23 php魔术方法

    本文对一些php中的魔术方法进行总结,魔术方法顾名思义就是具备神奇功能的方法(function).魔术方法通常在某些特定情况下自动触发,不能用实例化变量名->方法名()来主动触发.不同的魔术方法 ...

  8. nodeJS从入门到进阶二(网络部分)

    一.网络服务器 1.http状态码 1xx: 表示普通请求,没有特殊含义 2xx:请求成功 200:请求成功 3xx:表示重定向 301 永久重定向 302 临时重定向 303 使用缓存(服务器没有更 ...

  9. Linu如何查看磁盘占用情况及处理办法

    free -h: 查看当前剩余的内存大小 df: 查看文件系统磁盘使用率,可能free -h得到的剩余空间还有很多,但是df查询得到的部分文件系统磁盘使用率较高 当发现磁盘使用率较高的时候,可以: 先 ...

  10. 代码实现排列组合【Java】

    一.代码实现 package zhen; import java.util.Arrays; public class Arrangement { /** * 计算阶乘数,即n! = n * (n-1) ...