SP839 Optimal marks(最小割)
SP839 Optimal marks(最小割)
给你一个无向图G(V,E)。 每个顶点都有一个int范围内的整数的标记。 不同的顶点可能有相同的标记。对于边(u,v),我们定义Cost(u,v)= mark [u] \(\oplus\) mark [v]。现在我们知道某些节点的标记了。你需要确定其他节点的标记,以使边的总成本尽可能小。(0 < N <= 500, 0 <= M <= 3000)
先来看一下异或的性质,由于每一位是独立的,我们可以把每一位拉出来分开考虑,变成32个子问题。
现在问题就变成了:一堆点是0,一堆点是1,一堆点没有标号,它们互相有一些边,一个边的权值只当一个点是0一个点是1时才是1,否则是0。求最小边权和
于是我们这样建图:(红色表示1,蓝色表示0,白色表示没有权值)
然后跑一个最小割即可。脑补一下,就是找出红色点势力和蓝色点势力的接触处的最小边数。
关于最小割建模的题,具体怎么操作,首先是定义割的含义,就是和s相连的点都定义成要选择的点,其它的点都不选择。关于边的值的定义,不能割的边设置成INF。这个算是套路。
由于题目要求点权和最小,因此我们应尽量让红色点最少。于是,跑完最大流以后,把从s能遍历到的点都标成1就可以满足红色点最少啦!(这个不会证,留坑。)
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn=505, maxm=3005, INF=1e9;
int T, n, m, k, src, dst;
inline int min(int x, int y){ return x<y?x:y; }
struct Edge{
int to, nxt, f;
}e[maxm*2+maxn], e1[maxm];
int fir[maxn], cnte;
void addedge(int x, int y, int v){
Edge &ed=e[++cnte];
ed.to=y; ed.nxt=fir[x]; ed.f=v; fir[x]=cnte; }
void RESET(){ cnte=1; memset(fir, 0, sizeof(fir)); }
int mark[maxn], gmark[maxn];
int dep[maxn], q[maxn], head, tail;
int bfs(){ //bfs来给图分层
head=tail=0; memset(dep, 0, sizeof(dep));
dep[src]=1; q[tail++]=src; int tmp;
while (head<tail){
tmp=q[head++];
for (int i=fir[tmp]; i>0; i=e[i].nxt)
if (e[i].f>0&&!dep[e[i].to]){
dep[e[i].to]=dep[tmp]+1;
q[tail++]=e[i].to;
}
}
return dep[dst]?1:0;
}
int cur[maxn];
int dfs(int u, int flow){ //flow表示从s流到当前点的最大流量 找出一条流
if (u==dst) return flow;
if (cur[u]==-1) return 0;
for (int i=(cur[u]?cur[u]:fir[u]); i>0; i=e[i].nxt){
cur[u]=i;
if (dep[e[i].to]==dep[u]+1&&e[i].f){
int minm=dfs(e[i].to, min(flow, e[i].f));
if (minm>0){
e[i].f-=minm; e[i^1].f+=minm;
return minm;
}
}
}
cur[u]=-1;
return 0;
}
void dinic(){
while (bfs()){
memset(cur, 0, sizeof(cur));
while (dfs(src, INF));
}
}
bool vis[maxn];
void findzero(int u){
vis[u]=true;
for (int i=fir[u]; i; i=e[i].nxt){
if (vis[e[i].to]||!e[i].f) continue;
findzero(e[i].to);
}
}
int uu[maxm], vv[maxm];
int main(){
scanf("%d", &T); int t;
while (T--){
scanf("%d%d", &n, &m); dst=n+1;
for (int i=0; i<m; ++i)
scanf("%d%d", &uu[i], &vv[i]);
scanf("%d", &k);
memset(mark, 0, sizeof(mark));
memset(gmark, 0, sizeof(gmark));
for (int i=1; i<=k; ++i){
scanf("%d", &t); gmark[t]=1;
scanf("%d", &mark[t]);
}
for (int i=0; i<31; ++i){
RESET();
for (int j=0; j<m; ++j)
addedge(uu[j], vv[j], 1), addedge(vv[j], uu[j], 1);
for (int j=1; j<=n; ++j){
if (!gmark[j]) continue;
if (mark[j]&(1<<i)) addedge(src, j, INF);
else addedge(j, dst, INF);
}
dinic();
memset(vis, 0, sizeof(vis)); findzero(src);
for (int j=1; j<=n; ++j)
if (vis[j]) mark[j]|=(1<<i);
}
for (int i=1; i<=n; ++i) printf("%d\n", mark[i]);
}
return 0;
}
SP839 Optimal marks(最小割)的更多相关文章
- 【BZOJ2400】Spoj 839 Optimal Marks 最小割
[BZOJ2400]Spoj 839 Optimal Marks Description 定义无向图中的一条边的值为:这条边连接的两个点的值的异或值. 定义一个无向图的值为:这个无向图所有边的值的和. ...
- 【BZOJ-2400】Spoj839Optimal Marks 最小割 + DFS
2400: Spoj 839 Optimal Marks Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 567 Solved: 202[Submit ...
- [SP839]Optimal Marks
luogu 题意 给你一个无向图\(G(V,E)\). 每个顶点都有一个int范围内的整数的标记. 不同的顶点可能有相同的标记. 对于边\((u,v)\),我们定义\(Cost(u,v)=\rm ma ...
- SPOJ839 Optimal Marks(最小割)
题目大概说给一张图,每个点都有权,边的权等于其两端点权的异或和,现已知几个点的权,为了使所有边的边权和最小,其他点的权值该是多少. 很有意思的一道题,完全看不出和网络流有什么关系. 考虑每个未知的点$ ...
- spoj 839 Optimal Marks(二进制位,最小割)
[题目链接] http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=17875 [题意] 给定一个图,图的权定义为边的两端点相抑或值的 ...
- SPOJ-OPTM Optimal Marks ★★(按位建图 && 最小割)
[题意]给出一个无向图,每个点有一个标号mark[i],不同点可能有相同的标号.对于一条边(u, v),它的权值定义为mark[u] xor mark[v].现在一些点的标号已定,请决定剩下点的标号, ...
- SPOJ 839 OPTM - Optimal Marks (最小割)(权值扩大,灵活应用除和取模)
http://www.spoj.com/problems/OPTM/ 题意: 给出一张图,点有点权,边有边权 定义一条边的权值为其连接两点的异或和 定义一张图的权值为所有边的权值之和 已知部分点的点权 ...
- SPOJ 839 Optimal Marks(最小割的应用)
https://vjudge.net/problem/SPOJ-OPTM 题意: 给出一个无向图G,每个点 v 以一个有界非负整数 lv 作为标号,每条边e=(u,v)的权w定义为该边的两个端点的标号 ...
- Optimal Marks SPOJ - OPTM (按位枚举-最小割)
题意:给一张无向图,每个点有其点权,边(i,j)的cost是\(val_i\ XOR \ val_j\).现在只给出K个点的权值,求如何安排其余的点,使总花费最小. 分析:题目保证权值不超过32位整型 ...
随机推荐
- VS编译linux项目生成静态库并在另一个项目中静态链接的方法
VS2017也推出很久了,在单位的时候写linux的服务端程序只能用vim,这让用惯了IDE的我很难受. 加上想自己撸一套linux上的轮子,决定用VS开工远程编写调试linux程序. 在window ...
- c# webapi2 实用详解
本文介绍webapi的使用知识 发布webapi的问题 配置问题 webapi的项目要前端访问,需要在web.config配置文件中添加如下配置 在system.webServer节点下面添加 < ...
- Profile配置
Profile是Spring用来针对不同环境对不同的配置提供支持的,全局Profile配置使用application-{profile}.properties application.properti ...
- Tomcat 不能正常启动
启动过程提示: Stopping ProtocolHandler ["http-bio-8080"] the JRE_HOME environment variable is no ...
- DAY15-HTTP协议简述
HTTP协议 一.HTTP协议简介 超文本传输协议(英文:HyperText Transfer Protocol,缩写:HTTP)是一种用于分布式.协作式和超媒体信息系统的应用层协议.HTTP是万维网 ...
- DAY13-前端之JavaScript
JavaScript概述 JavaScript的历史 1992年Nombas开发出C-minus-minus(C--)的嵌入式脚本语言(最初绑定在CEnvi软件中),后将其改名ScriptEase(客 ...
- php中COM函数的使用
php里的com类可以操作window系统上的东西 例如:可以在本地打开一个word文档,然后写入东西,只用于window系统 需要加载php_com_dotnet.dll模块 $word = n ...
- sql编写注意
DROP TABLE IF EXISTS `imooc_pro`; CREATE TABLE `imooc_pro`( `id` int unsigned auto_increment key, `p ...
- Centos彻底完全删除已安装软件的办法
1.查询是否安装了软件 rpm -qa | grep -i 软件名 rpm -qa | grep php 2.删除已安装的软件包 根据第一步显示的软件包名,一个个删除 sudo rpm -e -- 包 ...
- C++实现矩阵的相加/相称/转置/求鞍点
1.矩阵相加 两个同型矩阵做加法,就是对应的元素相加. #include<iostream> using namespace std; int main(){ int a[3][3]={{ ...