SPOJ839 OPTM - Optimal Marks
闵神讲网络流应用的例题,来水一水
要写出这道题,需要深入理解两个概念,异或和最小割。
异或具有相对独立性,所以我们把每一位拆开来看,即做大概$32$次最小割。然后累加即可。
然后是最小割把一张图分割成两个集合,简单看就是0集合和1集合。
简单的建图:
原图不变,改成双向边,所有的流量限制为1。然后所有S点向点权为1的连边,点权为0的向T连边,容量都是正无穷。
为什么这样建?首先看,最小割把一张图分成两个点集。而因为我们的流量限制可以让最小割只割真实存在的边,而割的也只有可能是跨越0集合和1集合的边。所以最后的最小割就是答案。
//SPOJ839
//by Cydiater
//2017.1.15
#include <iostream>
#include <cmath>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <iomanip>
#include <queue>
#include <map>
#include <algorithm>
#include <cstring>
#include <string>
#include <bitset>
#include <set>
#include <vector>
using namespace std;
#define ll long long
#define up(i,j,n) for(int i=j;i<=n;i++)
#define down(i,j,n) for(int i=j;i>=n;i--)
#define cmax(a,b) a=max(a,b)
#define cmin(a,b) a=min(a,b)
#define Auto(i,node) for(int i=LINK[node];i;i=e[i].next)
#define vci vector<int>
const int MAXN=1e4+5;
const int oo=0x3f3f3f3f;
inline int read(){
char ch=getchar();int x=0,f=1;
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int LINK[MAXN],len=0,N,M,Val[MAXN],TT,Q,tag[MAXN],S,T,ans=0,q[MAXN],head,tail,level[MAXN];
bool used[MAXN],vis[MAXN];
vci E[MAXN];
struct edge{
int x,y,next,flow,reverse;
}e[MAXN<<1];
namespace solution{
void Clear(){
len=0;
memset(LINK,0,sizeof(LINK));
}
inline void insert(int x,int y,int flow,int delta){
e[++len].next=LINK[x];LINK[x]=len;e[len].y=y;
e[len].flow=flow;e[len].reverse=len+delta;
}
void Prepare(){
Clear();
N=read();M=read();
S=N+1;T=N+2;
up(i,1,N)E[i].clear();
up(i,1,M){
int x=read(),y=read();
E[x].push_back(y);
E[y].push_back(x);
}
Q=read();
memset(Val,0,sizeof(Val));
memset(used,0,sizeof(used));
while(Q--){
int node=read(),val=read();
Val[node]=val;used[node]=1;
}
}
void Build(){
Clear();
up(i,1,N){
int siz=E[i].size();
up(j,0,siz-1){
insert(i,E[i][j],1,1);
insert(E[i][j],i,0,-1);
}
}
up(i,1,N){
if(tag[i]==1){
insert(S,i,oo,1);
insert(i,S,0,-1);
}else if(tag[i]==0){
insert(i,T,oo,1);
insert(T,i,0,-1);
}
}
}
bool makelevel(){
memset(level,-1,sizeof(level));
head=1;tail=0;level[S]=0;q[++tail]=S;
for(;head<=tail;head++){
int node=q[head];
Auto(i,node)if(e[i].flow>0&&level[e[i].y]==-1){
level[e[i].y]=level[node]+1;
q[++tail]=e[i].y;
}
}
return level[T]!=-1;
}
int addflow(int node,int flow){
if(node==T) return flow;
int maxflow=0,d=0;
Auto(i,node)if(level[e[i].y]==level[node]+1&&e[i].flow>0){
if(d=addflow(e[i].y,min(e[i].flow,flow-maxflow))){
maxflow+=d;
e[i].flow-=d;
e[e[i].reverse].flow+=d;
}
}
if(maxflow==0)level[node]=-1;
return maxflow;
}
void Dinic(int dig){
int d;
while(makelevel())
while(d=addflow(S,oo))
ans+=(d<<dig);
}
void DFS(int node){
vis[node]=1;tag[node]=1;
Auto(i,node)if(e[i].flow>0&&!vis[e[i].y])
DFS(e[i].y);
}
void Solve(){
up(dig,0,31){
up(i,1,N){
if(used[i]) tag[i]=((Val[i]&(1<<dig))>>dig);
else tag[i]=-1;
}
Build();
Dinic(dig);
up(i,1,N)tag[i]=0;
memset(vis,0,sizeof(vis));
DFS(S);
up(i,1,N)if(!used[i])Val[i]|=(tag[i]<<dig);
}
up(i,1,N)printf("%d\n",Val[i]);
}
}
int main(){
//freopen("input.in","r",stdin);
using namespace solution;
TT=read();
while(TT--){
Prepare();
Solve();
}
return 0;
}
SPOJ839 OPTM - Optimal Marks的更多相关文章
- 图论(网络流):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 ...
- 【SPOJ839】Optimal Marks 网络流
You are given an undirected graph G(V, E). Each vertex has a mark which is an integer from the range ...
- SPOJ 839 OPTM - Optimal Marks (最小割)(权值扩大,灵活应用除和取模)
http://www.spoj.com/problems/OPTM/ 题意: 给出一张图,点有点权,边有边权 定义一条边的权值为其连接两点的异或和 定义一张图的权值为所有边的权值之和 已知部分点的点权 ...
- spoj 839 OPTM - Optimal Marks&&bzoj 2400【最小割】
因为是异或运算,所以考虑对每一位操作.对于所有已知mark的点,mark的当前位为1则连接(s,i,inf),否则连(i,t,inf),然后其他的边按照原图连(u,v,1),(v,u,1),跑最大流求 ...
- Luogu SP839 OPTM - Optimal Marks(按位最小割)
这道题和 BZOJ 2400 是一道题,不多讲了 CODE #include <cstdio> #include <cstring> #include <vector&g ...
- [SPOJ839]Optimal Marks
[SPOJ839]Optimal Marks 试题描述 You are given an undirected graph \(G(V, E)\). Each vertex has a mark wh ...
- SP839 Optimal marks(最小割)
SP839 Optimal marks(最小割) 给你一个无向图G(V,E). 每个顶点都有一个int范围内的整数的标记. 不同的顶点可能有相同的标记.对于边(u,v),我们定义Cost(u,v)= ...
- Optimal Marks(optimal)
Optimal Marks(optimal) 题目描述 定义无向图边的值为这条边连接的两个点的点权异或值. 定义无向图的值为无向图中所有边的值的和. 给定nn个点mm条边构成的图.其中有些点的权值是给 ...
随机推荐
- Dom++完美版得到元素到html的距离6/4/21
function getTop(obj) { var pos={left:0,top:0}; while(obj) { pos.left+=obj.offsetLeft; pos.top+=obj.o ...
- HDU 4612 Warm up(双连通分量缩点+求树的直径)
思路:强连通分量缩点,建立一颗新的树,然后求树的最长直径,然后加上一条边能够去掉的桥数,就是直径的长度. 树的直径长度的求法:两次bfs可以求,第一次随便找一个点u,然后进行bfs搜到的最后一个点v, ...
- elasticsearch 手动控制分片分布
elasticsearch可以通过reroute api来手动进行索引分片的分配. 不过要想完全手动,必须先把cluster.routing.allocation.disable_allocatio ...
- struts1,struts2,hibernate,spring的运行原理结构图
一.struts1运行原理 1.初始化:struts框架的总控制器ActionServlet是一个Servlet,它在web.xml中配置成自动启动的Servlet,在启动时总控制器会读取配置文件(s ...
- CentOS Hadoop安装配置详细
总体思路,准备主从服务器,配置主服务器可以无密码SSH登录从服务器,解压安装JDK,解压安装Hadoop,配置hdfs.mapreduce等主从关系. 1.环境,3台CentOS7,64位,Hadoo ...
- 把APP做成libary的注意事项
首先把build.gradle(app里的),里面改成这样 apply plugin: 'com.android.library'然后删掉applicationId这一行 注意,千万不能用注解,要把所 ...
- ratingbar设置不可调节星星数量
<RatingBar android:id="@+id/rb_bar" android:layout_width="wrap_content" andro ...
- ubuntu上面安装eclipse android到adt下载方法
如果自动安装有问题的话,就需要手动安装,其实是差不多的,唯一不同的就是手动下载ADT插件包,http://dl.google.com/android/ADT-0.9.6.zip ,可以下载到. 版本号 ...
- 转 Fragment 和 FragmentActivity的使用
今天学习下 Android中的 Fragment 和 FragmentActivity,因为没有4.0手机,平台是2.3.3 所以我是使用 v4 support 包来进行学习. 要想用Fragment ...
- jsp 获取cookie 的值的方法
Cookie cookies[]=request.getCookies(); //读出用户硬盘上的Cookie,并将所有的Cookie放到一个cookie对象数组里面 Cookie sCookie=n ...