https://vjudge.net/problem/SPOJ-OPTM

题意:

给出一个无向图G,每个点 v 以一个有界非负整数 lv 作为标号,每条边e=(u,v)的权w定义为该边的两个端点的标号的异或值,即W=lu XOR lv。现已知其中部分点的标号,求使得该图的总边权和最小的标号赋值。即最小化:

思路:

这道题目在刘伯涛的论文里讲得十分的详细,看看论文就可以啦。

XOR运算是根据二进制的每一位来计算的,,并且因为每一位都是相互独立的,互不影响,所以可以转化为下式:

接下来对于每一位都新建图,对于已经标号的顶点来说,如果该位是1,则与源点相连,否则与汇点相连,容量均为INF。如果本来就相连的点还是需要相连的,容量为1。对于每个还没有标号的点来说,在这一位的取值要么是1,要么是0,这就很符合最小割。在跑完最大流之后,只需要从源点出发,凡是能到达的点都是取值为1的。

 #include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<vector>
#include<stack>
#include<queue>
#include<cmath>
#include<map>
#include<set>
using namespace std;
typedef long long ll;
typedef pair<int,int> pll;
const int INF = 0x3f3f3f3f;
const int maxn = + ; int n, m, k;
int val[maxn];
int ans[maxn];
int vis[maxn];
int mp[maxn][maxn]; struct Edge
{
int from,to,cap,flow;
Edge(int u,int v,int w,int f):from(u),to(v),cap(w),flow(f){}
}; struct Dinic
{
int n,m,s,t;
vector<Edge> edges;
vector<int> G[maxn];
bool vis[maxn];
int cur[maxn];
int d[maxn]; void init(int n)
{
this->n=n;
for(int i=;i<n;++i) G[i].clear();
edges.clear();
} void AddEdge(int from,int to,int cap)
{
edges.push_back( Edge(from,to,cap,) );
edges.push_back( Edge(to,from,,) );
m=edges.size();
G[from].push_back(m-);
G[to].push_back(m-);
} bool BFS()
{
queue<int> Q;
memset(vis,,sizeof(vis));
vis[s]=true;
d[s]=;
Q.push(s);
while(!Q.empty())
{
int x=Q.front(); Q.pop();
for(int i=;i<G[x].size();++i)
{
Edge& e=edges[G[x][i]];
if(!vis[e.to] && e.cap>e.flow)
{
vis[e.to]=true;
d[e.to]=d[x]+;
Q.push(e.to);
}
}
}
return vis[t];
} int DFS(int x,int a)
{
if(x==t || a==) return a;
int flow=, f;
for(int &i=cur[x];i<G[x].size();++i)
{
Edge &e=edges[G[x][i]];
if(d[e.to]==d[x]+ && (f=DFS(e.to,min(a,e.cap-e.flow) ) )>)
{
e.flow +=f;
edges[G[x][i]^].flow -=f;
flow +=f;
a -=f;
if(a==) break;
}
}
return flow;
} int Maxflow(int s,int t)
{
this->s=s; this->t=t;
int flow=;
while(BFS())
{
memset(cur,,sizeof(cur));
flow +=DFS(s,INF);
}
return flow;
}
}DC; void dfs(int u, int x)
{
vis[u]=;
ans[u]+=x;
for(int i=;i<DC.G[u].size();i++)
{
Edge& e=DC.edges[DC.G[u][i]];
if(!vis[e.to] && e.cap>e.flow)
dfs(e.to,x);
}
} void solve()
{
int src=,dst=n+;
int bite=;
while(true)
{
DC.init(dst+);
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
if(mp[i][j]) DC.AddEdge(i,j,); bool flag=false;
for(int i=;i<=n;i++)
{
if(val[i]!=-)
{
if(val[i]>=)
{
flag=true;
}
if(val[i]&)
{
DC.AddEdge(src,i,INF);
}
else
{
DC.AddEdge(i,dst,INF);
}
val[i]>>=;
}
} if(!flag) break;
DC.Maxflow(src,dst);
memset(vis,,sizeof(vis));
dfs(src,bite);
bite<<=;
}
} int main()
{
//freopen("in.txt","r",stdin);
int T;
scanf("%d",&T);
while(T--)
{
memset(mp,,sizeof(mp));
scanf("%d%d",&n,&m);
for(int i=;i<m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
mp[u][v]=mp[v][u]=;
}
memset(val,-,sizeof(val));
scanf("%d",&k);
for(int i=;i<k;i++)
{
int u,v;
scanf("%d%d",&u,&v);
val[u]=v;
}
memset(ans,,sizeof(ans));
solve();
for(int i=;i<=n;i++)
{
printf("%d\n",ans[i]);
}
}
return ;
}

SPOJ 839 Optimal Marks(最小割的应用)的更多相关文章

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

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

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

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

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

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

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

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

  5. BZOJ 2400: Spoj 839 Optimal Marks (按位最小割)

    题面 一个无向图,一些点有固定权值,另外的点权值由你来定. 边的值为两点的异或值,一个无向图的值定义为所有边的值之和. 求无向图的最小值 分析 每一位都互不干扰,按位处理. 用最小割算最小值 保留原图 ...

  6. BZOJ2400: Spoj 839 Optimal Marks

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

  7. 【BZOJ-2400】Spoj839Optimal Marks 最小割 + DFS

    2400: Spoj 839 Optimal Marks Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 567  Solved: 202[Submit ...

  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. Linux基础命令---显示文本look

    look 显示文件中以特定字符串开始的行.在look执行二进制搜索时,必须对文件中的行进行排序.如果未指定文件,则使用文件“/usr/share/dict/words“,只比较字母数字字符,忽略字母字 ...

  2. web前端学习路线(含20个真实web开发项目集合)

    目前web前端工程师日均岗位缺口已经超过50000,随着互联网+的深入发展,html5作为前端展示技术,市场人才需求量将呈直线上涨. Web前端工程师的岗位职责是利用HTML.CSS.Java.DOM ...

  3. Java 注释规范

    基本的要求: 1.注释形式统一 在整个应用程序中,使用具有一致的标点和结构的样式来构造注释.如果在其它项目中发现它们的注释规范与这份文档不同,按照这份规范写代码,不要试图在既成的规范系统中引入新的规范 ...

  4. axios post参数为空

    今天在360浏览器访问时后台接收不到参数,但是用谷歌浏览器就能收到传入的值.

  5. Markdown使用笔记

    下载地址:http://markdownpad.com/ 简明版 Markdown 语法说明(简体中文版) 完整版 Markdown 语法说明(简体中文版) 官方文档:http://www.markd ...

  6. mybatis的dao的mapper写法

    ## MyBatis的Dao编写[mapper代理方式实现] step1: 写一个接口,并写抽象方法 package com.sjl.mapper; import com.sjl.model.User ...

  7. Linux内核线程创建

    本文旨在简单介绍一下Linux内核线程: 先举个例子: 不插U盘,在Linux命令行中输入:ps -el:然后插上U盘,再次输入:ps -el 会发现多出了下面一行(当然还会有其他的,比如scsi相关 ...

  8. scrapy 日志处理

    Scrapy生成的调试信息非常有用,但是通常太啰嗦,你可以在Scrapy项目中的setting.py中设置日志显示等级: LOG_LEVEL = 'ERROR' 日志级别 Scrapy日志有五种等级, ...

  9. JDK常用命令(三)jmap

    jmap jmap,Java Memory Map.主要用于打印指定Java进程(或核心文件.远程调试服务器)的共享对象内存映射或堆内存细节. jmap命令可以获得运行中的jvm的堆的快照,从而可以离 ...

  10. Builgen 插件——IntelliJ IDEA和Eclipse Java Bean Builder模式代码生成器-比lombok更符合需求

    builder模式在越来越多的项目中使用,类似于alibaba fastjson JSONObject.fluentPut(),调用一个方法后返回这个对象本身,特别适合构建一些参数超级多的对象,代码优 ...