SPOJ 839 OPTM - Optimal Marks (最小割)(权值扩大,灵活应用除和取模)
http://www.spoj.com/problems/OPTM/
题意:
给出一张图,点有点权,边有边权
定义一条边的权值为其连接两点的异或和
定义一张图的权值为所有边的权值之和
已知部分点的点权,自定义其余点的点权
使图的权值最小,并在此基础上使点权和最小
输出点的权值
异或——按位做
那么题目就变成了已知一些点的点权为0/1,自定义剩余点的点权0/1
使01相遇的边最少
(01相遇指的是一条边连接的两点的点权不同)
我们建立最小割模型:
先不考虑第二问
源点向已知点的点权为0的点连正无穷的边
已知点的点权为1的点向汇点连正无穷的边
然后把原图加进去,原图中若存在u和v之间的边,就加入u向v,v向u 流量为1的边
这样最小割割的时候只会割流量为1的边,割一条边表示这条边连接的两点点权不同
最后在残量网络上,点与源点相连则代表点权为0,点与汇点相连代表点权为1
再来考虑第二问
第二问相当于最后残量网络上,点既可以与源点连又可以与汇点连的时候,选择与源点连
将所有不与源点相连的点x,加上源点向x流量为1的边
这样如果x最后选择与汇点相连,那么它就要多花费1的代价
这就使x尽可能的与源点相连
那么这岂不是影响了第一问的答案?
用点儿小技巧
原来是原图中若存在u和v之间的边,就加入u向v,v向u 流量为1的边
改成 原图中若存在u和v之间的边,就加入u向v,v向u 流量为10000的边
然后第一问相当于最最小割/10000
第二问相当于最小割%10000
最后查询与源点分离的点时,不是源点连出去的流量为1的边满流
而是dinic最后一次分层遍历遍历不到的点

S->2的边虽然满流,但是仍可以通过S->3->2 所以2是与源点相连的点
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream> using namespace std; #define N 502
#define M 3001 const int inf=1e9; struct node
{
int u,v;
}e[]; int num[N]; int ans[N]; int front[N],to[M*],nxt[M*],cap[M*],tot;
int src,decc;
int lev[N],cur[N]; queue<int>q; void read(int &x)
{
x=; char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) { x=x*+c-''; c=getchar(); }
} void add(int u,int v,int w)
{
to[++tot]=v; nxt[tot]=front[u]; front[u]=tot; cap[tot]=w;
to[++tot]=u; nxt[tot]=front[v]; front[v]=tot; cap[tot]=;
} bool bfs()
{
for(int i=src;i<=decc;++i) lev[i]=-,cur[i]=front[i];
while(!q.empty()) q.pop();
q.push(src);
lev[src]=;
int now;
while(!q.empty())
{
now=q.front();
q.pop();
for(int i=front[now];i;i=nxt[i])
if(cap[i] && lev[to[i]]==-)
{
lev[to[i]]=lev[now]+;
if(to[i]==decc) return true;
q.push(to[i]);
}
}
return false;
} int dinic(int now,int flow)
{
if(now==decc) return flow;
int rest=,delta;
for(int &i=cur[now];i;i=nxt[i])
if(cap[i] && lev[to[i]]>lev[now])
{
delta=dinic(to[i],min(flow-rest,cap[i]));
if(delta)
{
rest+=delta;
cap[i]-=delta; cap[i^]+=delta;
if(rest==flow) break;
}
}
if(rest!=flow) lev[now]=-;
return rest;
} int main()
{
int T,n,m,k,x;
// int flow;
// long long ans1,ans2;
read(T);
while(T--)
{
memset(num,-,sizeof(num));
memset(ans,,sizeof(ans));
//ans1=ans2=0;
tot=;
read(n); read(m);
for(int i=;i<=m;++i) read(e[i].u),read(e[i].v);
read(k);
for(int i=;i<=k;++i)
{
read(x);
read(num[x]);
}
decc=n+;
for(int bit=;bit<;++bit)
{
memset(front,,sizeof(front));
tot=;
for(int i=;i<=n;++i)
if(num[i]!=-)
{
if(num[i]&<<bit) add(i,decc,inf),add(src,i,);
else add(src,i,inf);
}
else add(src,i,);
for(int i=;i<=m;++i)
{
add(e[i].u,e[i].v,);
add(e[i].v,e[i].u,);
}
// flow=0;
while(bfs())
dinic(src,inf);
// ans1+=1LL*flow/10000*(1<<bit);
// ans2+=1LL*flow%10000*(1<<bit);
for(int i=;i<=n;++i)
if(lev[i]==-) ans[i]|=<<bit;
}
// printf("%lld\n%lld",ans1,ans2);
for(int i=;i<=n;++i) printf("%d\n",ans[i]);
}
}
SPOJ 839 OPTM - Optimal Marks (最小割)(权值扩大,灵活应用除和取模)的更多相关文章
- spoj 839 OPTM - Optimal Marks&&bzoj 2400【最小割】
因为是异或运算,所以考虑对每一位操作.对于所有已知mark的点,mark的当前位为1则连接(s,i,inf),否则连(i,t,inf),然后其他的边按照原图连(u,v,1),(v,u,1),跑最大流求 ...
- 【BZOJ2400】Spoj 839 Optimal Marks 最小割
[BZOJ2400]Spoj 839 Optimal Marks Description 定义无向图中的一条边的值为:这条边连接的两个点的值的异或值. 定义一个无向图的值为:这个无向图所有边的值的和. ...
- 图论(网络流):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 ...
- SPOJ OPTM - Optimal Marks
OPTM - Optimal Marks no tags You are given an undirected graph G(V, E). Each vertex has a mark whic ...
- The Minimum Cycle Mean in a Digraph 《有向图中的最小平均权值回路》 Karp
文件链接 Karp在1977年的论文,讲述了一种\(O(nm)\)的算法,用来求有向强连通图中最小平均权值回路(具体问题请参照这里) 本人翻译(有删改): 首先任取一个节点 \(s\) ,定义 \(F ...
- 【BZOJ-2400】Spoj839Optimal Marks 最小割 + DFS
2400: Spoj 839 Optimal Marks Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 567 Solved: 202[Submit ...
- SPOJ839 OPTM - Optimal Marks
传送门 闵神讲网络流应用的例题,来水一水 要写出这道题,需要深入理解两个概念,异或和最小割. 异或具有相对独立性,所以我们把每一位拆开来看,即做大概$32$次最小割.然后累加即可. 然后是最小割把一张 ...
- spoj 1693 COCONUTS - Coconuts【最小割】
s向所有信仰1的人连(s,i,1),所有信仰0的人连(i,t,1),对于朋友关系,连接双向边,流量为1.跑最大流的结果即为答案. 考虑这样做的意义.最小割就是把总点集分割为两个点集S,T,使得所有\( ...
- hdu 1565&hdu 1569(网络流--最小点权值覆盖)
方格取数(1) Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Su ...
随机推荐
- Daemon Thread [shirocache] (Running)
shiro cache的原理 https://cwiki.apache.org/confluence/display/SHIRO/Caching shirocache这个线程相关的内容
- 记Git报错-refusing to merge unrelated histories
记Git报错-refusing to merge unrelated histories 系统:win7 git版本: 2.16.2.windows.1 问题 1.本地初始化了git仓库,放了一些 ...
- [转帖] ASP ASPX 等知识
asp.asp.net..aspx..ascx..ashx的简单说明 https://www.cnblogs.com/jhcelue/p/6736147.html ASP是动态server页面(Act ...
- Angular require(抄别的)
require参数的值可以用下面的前缀进行修饰,这会改变查找控制器时的行为:?如果在当前指令中没有找到所需要的控制器,会将null作为传给link函数的第四个参数.^如果添加了^前缀,指令会在上游的指 ...
- sql优化问题笔记(mysql)
相信大家平时面试都会遇到这个问题:平时你都是怎么对sql进行调优的? 此篇文章相当于一个随便笔记,根据朋友们的聊天记录整理而成,如有不对,请指正! 注意:这篇是以mysql整理的 查看sql计划分析 ...
- linux中内存使用原理
首先介绍一下linux中内存是如何使用的. 当有应用需要读写磁盘数据时,由系统把相关数据从磁盘读取到内存,如果物理内存不够,则把内存中的部分数据导入到磁盘,从而把磁盘的部分空间当作虚拟内存 来使用,也 ...
- r=a*(1-sinx)
a=-2*pi:.001:2*pi; %设定角度b=(1-sin(a)); %设定对应角度的半径polar(a, b,'r') %绘图 夏目漱石“今夜月色很好” 王家卫“我已经很久没有坐过摩托车了,也 ...
- python---面对对象的三大特征
一.三大特征 面对对象的三大特征:继承.多态和封装,继承在面向对象类的创建中非常常见. 1.继承 为什么会有继承,当我们要创建一个新类的时候,发现他有很多属性或者反法都和我们另一个类的方法相同,这时我 ...
- 使用TortoiseSVN创建版本库
1. 使用TortoiseSVN创建版本库 在SVN中,为了便于创建分支和标签,我们习惯于将Repository版本库的结构布置为:/branches,/tags,/trunk.分别代表分支,标签以及 ...
- BZOJ2215[Poi2011]Conspiracy——2-SAT+tarjan缩点
题目描述 Byteotia的领土被占领了,国王Byteasar正在打算组织秘密抵抗运动.国王需要选一些人来进行这场运动,而这些人被分为两部分:一部分成为同谋者活动在被占领区域,另一部分是后勤组织在未被 ...