题面

一个无向图,一些点有固定权值,另外的点权值由你来定.

边的值为两点的异或值,一个无向图的值定义为所有边的值之和.

求无向图的最小值

分析

每一位都互不干扰,按位处理.

用最小割算最小值

  • 保留原图的边,容量为1
  • 如果当前点这一位是1,就从S连向当前点,容量为∞\infty∞
  • 如果当前点这一位是0,就从当前点连向T,容量为∞\infty∞

    那么这样一来,分在S一边就表示选,分在T一边就表示不选.如果相邻的两点在不同的集合,中间的边就必须断掉,造成1的代价,那么刚好相当于中间的边的值.

跑一遍最小割然后从S开始搜,不搜满流的边(也就是被割开的边),加上答案即可

  • 对于在边值相等的情况下,要求点值最小的正确性如下:

    在我们的最小割中,被划分在S一边表示选,那么一条增广路径上有多条满流边的时候,我们的搜索处理方法是遇到满流边就不往下走.所以我们割的边一定最靠近S集,也就是尽量地多让剩下点被分在T集(也就是选0),这样就满足了在同等情况下尽量选0使得点值最小.
  • 另一种方法是把边值设为10000,点值设为1.那么最小边值之和就是ans/10000,在此情况下的最小点值就是ans%10000

CODE

#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
typedef long long LL;
template<typename T>inline void read(T &num) {
char ch; int flg=1;
while((ch=getchar())<'0'||ch>'9')if(ch=='-')flg=-flg;
for(num=0;ch>='0'&&ch<='9';num=num*10+ch-'0',ch=getchar());
num*=flg;
}
const int inf = 1e9;
const int MAXN = 505;
const int MAXM = 20005;
int n, m, fir[MAXN], S, T, cnt;
struct edge { int to, nxt; LL c; }e[MAXM];
inline void add(int u, int v, LL cc, LL rc=0) {
e[cnt] = (edge){ v, fir[u], cc }; fir[u] = cnt++;
e[cnt] = (edge){ u, fir[v], rc }; fir[v] = cnt++;
}
int dis[MAXN], vis[MAXN], info[MAXN], cur, q[MAXN];
inline bool bfs() {
int head = 0, tail = 0;
vis[S] = ++cur; q[tail++] = S;
while(head < tail) {
int u = q[head++];
for(int i = fir[u]; ~i; i = e[i].nxt)
if(e[i].c && vis[e[i].to] != cur)
vis[e[i].to] = cur, dis[e[i].to] = dis[u] + 1, q[tail++] = e[i].to;
}
if(vis[T] == cur) memcpy(info, fir, (T+1)<<2);
return vis[T] == cur;
}
LL dfs(int u, LL Max) {
if(u == T || !Max) return Max;
LL flow=0, delta;
for(int &i = info[u]; ~i; i = e[i].nxt)
if(e[i].c && dis[e[i].to] == dis[u] + 1 && (delta=dfs(e[i].to, min(e[i].c, Max-flow)))) {
e[i].c -= delta, e[i^1].c += delta, flow += delta;
if(flow == Max) return flow;
}
return flow;
}
inline LL dinic() {
memset(vis, 0, sizeof vis);
LL flow=0, x;
while(bfs()) {
while((x=dfs(S, inf))) flow+=x;
}
return flow;
}
int A[MAXN], X[2005], Y[2005]; LL ans1, ans2;
bool flg[MAXN];
void Getans2(int u, int val) {
if(u) ans2 += val; flg[u] = 1;
for(int i = fir[u]; ~i; i = e[i].nxt)
if(e[i].c && !flg[e[i].to])
Getans2(e[i].to, val);
}
int main () {
read(n); read(m); S = 0, T = n+1;
for(int i = 1; i <= n; ++i) read(A[i]);
for(int i = 1; i <= m; ++i) read(X[i]), read(Y[i]);
for(int bit = 0; bit < 30; ++bit) {
memset(fir, -1, sizeof fir); cnt = 0;
for(int i = 1; i <= m; ++i) add(X[i], Y[i], 1, 1);
for(int i = 1; i <= n; ++i) {
if(A[i] < 0) continue;
if(A[i]&(1<<bit)) add(S, i, inf);
else add(i, T, inf);
}
memset(flg, 0, sizeof flg);
ans1 += dinic() * (1<<bit);
Getans2(S, 1<<bit);
}
printf("%lld\n%lld\n", ans1, ans2);
}

Upd:Upd:Upd:不开long longlong\ longlong long毁一生

BZOJ 2400: Spoj 839 Optimal Marks (按位最小割)的更多相关文章

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

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

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

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

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

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

  4. BZOJ2400: Spoj 839 Optimal Marks

    Description 定义无向图中的一条边的值为:这条边连接的两个点的值的异或值. 定义一个无向图的值为:这个无向图所有边的值的和. 给你一个有n个结点m条边的无向图.其中的一些点的值是给定的,而其 ...

  5. spoj 839 Optimal Marks(二进制位,最小割)

    [题目链接] http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=17875 [题意] 给定一个图,图的权定义为边的两端点相抑或值的 ...

  6. SPOJ 839 Optimal Marks(最小割的应用)

    https://vjudge.net/problem/SPOJ-OPTM 题意: 给出一个无向图G,每个点 v 以一个有界非负整数 lv 作为标号,每条边e=(u,v)的权w定义为该边的两个端点的标号 ...

  7. 【bzoj2400】Spoj 839 Optimal Marks 网络流最小割

    题目描述 定义无向图中的一条边的值为:这条边连接的两个点的值的异或值. 定义一个无向图的值为:这个无向图所有边的值的和. 给你一个有n个结点m条边的无向图.其中的一些点的值是给定的,而其余的点的值由你 ...

  8. 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 ...

  9. 图论(网络流):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 ...

随机推荐

  1. hadoop在eclipse当中如何添加源码?

    [学习笔记] /*org.apache.hadoop.mapreduce.Mapper.Context,java.lang.InterruptedException,想看map的源代码,按contro ...

  2. VMware安装windows7系统

    1.进入VMware系统,选择创建新的虚拟机 2.进入安装页面,选择自定义安装 3.选择虚拟机硬件兼容性,选择与自己软件相匹配的硬件兼容性 4.选择下一步后,选择稍后安装操作系统 5.选择客户机操作系 ...

  3. SAS学习笔记44 宏函数

    类SAS函数的宏函数 该部分函数共5个,其无论是名字.语法.功能都与SAS函数类似,只是在函数名前多了一个“%”.这5个宏函数分别是: %INDEX %LENGTH %SCAN %SUBSTR %UP ...

  4. SAS学习笔记41 宏变量存储及间接引用

    Macro Variables存储在“Symbol Table”中.它是由Macro Processor在SAS启动时自动创建并维护的.SAS提供了一张视图来供我们查看Symbol Table中的内容 ...

  5. PAT-1012 The Best Rank (25 分) 查询分数对应排名(包括并列)

    To evaluate the performance of our first year CS majored students, we consider their grades of three ...

  6. sublimeText3汉化安装教程 附注册码

    sublimeText3汉化安装教程 sublimeText3 很不错,前面几天下了vscore学习Node.js,感觉有点懵,今天下载sublimeText3,遇到的一些小问题,在这里说说: 百度云 ...

  7. .NET CORE 下 MariaDB DBfirst 生成model层 并配置连接参数

    1.首先新建一个类库,然后通过NuGet安装下面三个包 2.然后在程序包管理器控制台中运行以下代码(ps:记得默认项目选择刚才新建的项目,同时设置为启动项) server 是服务器地址 databas ...

  8. Asp.Net Core 轻松学系列-1阅读指引目录

    https://www.cnblogs.com/viter/p/10474091.html 目录 前言 1. 从安装到配置 2. 业务实现 3. 日志 4. 测试 5. 缓存使用 6.网络和通讯 7. ...

  9. Linux--CentOS 安装 Docker 教程

    本文主要介绍 CentOS 系统安装 Docker 的流程. 前提条件 OS 要求 CentOS7: The centos-extras repository must be enabled. Thi ...

  10. 使用zrender.js绘制体温单(1)

    之前公司请外包做了一个体温单使用的zrender.js 但是代码比较复杂维护性比较低再加上自己技术也不行 最近闲下来的时候看了一下zrender的官网慢慢的摸索并读了下之前的代码,感觉实际并不难,就自 ...