传送门

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

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

每一位上,确定的点值为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. Word 插入目录详细教程 -- 视频教程(6)

    >> 视频教程链接:B站,速度快,清晰 更多关于插入目录的方法,参看:Word插入目录系列 未完 ...... 点击访问原文(进入后根据右侧标签,快速定位到本文)

  2. LocalStack和Local对象实现栈的管理

    flask里面有两个重要的类Local和LocalStack 输入from flask import globals 左键+ctrl点globals进入源码,进去后找57行 flask只会实例化出这两 ...

  3. 关于ElasticSearch的堆内存设置与优化

    1.什么是堆内存?Java 中的堆是 JVM 所管理的最大的一块内存空间,主要用于存放各种类的实例对象.在 Java 中,堆被划分成两个不同的区域:- 新生代 ( Young ).- 老年代 ( Ol ...

  4. Bootstrap 遮罩插件jquery.mloading

    使用方法 将jquery.mloading.js和jquery.mloading.css引入到页面,调用: $(element).mLoading({ text:"",//加载文字 ...

  5. 阿里巴巴 Java 开发手册 (七) 控制语句

    1. [强制]在一个 switch 块内,每个 case 要么通过 break/return 等来终止,要么注释说明程 序将继续执行到哪一个 case 为止:在一个 switch 块内,都必须包含一个 ...

  6. 在.net core中数据操作的两种方式(Db first && Code first)

    在开发过程中我们通常使用的是Db first这种模式,而在.net core 中推荐使用的却是 code first 反正我是很不习惯这种开发模式 于是就搜寻整个微软的官方文档,终于找到了有关.net ...

  7. 把项目通过maven生产源码包和文档包并发布到自己的私服上

    <!-- 把项目通过maven生产源码包和文档包并发布到自己的私服上 执行maven命令,mvn clean package,执行完成后 命令:mvn deploy 就可以发布到你自己的私服上了 ...

  8. Python特色的序列解包、链式赋值、链式比较

    一.序列解包 序列解包(或可迭代对象解包):解包就是从序列中取出其中的元素的过程,将一个序列(或任何可迭代对象)解包,并将得到的值存储到一系列变量中. 一般情况下要解包的序列包含的元素个数必须与你在等 ...

  9. robotframework的学习笔记(十八)——RequestsLibrary库的API介绍

    requestsLibrary的关键字不多,常用的就几个. Create Session: 创建一个session,连接某个服务器.Create Ntlm Session: 也是创建一个session ...

  10. 红米手机使用应用沙盒一键修改sdk信息

    前面文章介绍了怎么在安卓手机上安装激活XPOSED框架,XPOSED框架的极强的功能各位都介绍过,能不修改APK的前提下,修改系统内核的参数,打个比方在某些应用情景,各位需要修改手机的某个系统参数,这 ...