OPTM-Optimal Marks-SPOJ839最小割
You are given an undirected graph G(V, E). Each vertex has a mark which is an integer from the range [0..231 – 1]. Different vertexes may have the same mark.
For an edge (u, v), we define Cost(u, v) = mark[u] xor mark[v].
Now we know the marks of some certain nodes. You have to determine the marks of other nodes so that the total cost of edges is as small as possible.
Input
The first line of the input data contains integer T (1 ≤ T ≤ 10) - the number of testcases. Then the descriptions of T testcases follow.
First line of each testcase contains 2 integers N and M (0 < N <= 500, 0 <= M <= 3000). N is the number of vertexes and M is the number of edges. Then M lines describing edges follow, each of them contains two integers u, v representing an edge connecting u and v.
Then an integer K, representing the number of nodes whose mark is known. The next K lines contain 2 integers u and p each, meaning that node u has a mark p. It’s guaranteed that nodes won’t duplicate in this part.
Output
For each testcase you should print N lines integer the output. The Kth line contains an integer number representing the mark of node K. If there are several solutions, you have to output the one which minimize the sum of marks. If there are several solutions, just output any of them.
Example
Input:
1
3 2
1 2
2 3
2
1 5
3 100
Output:
5
4
100
在Amber的最小割论文上看到的一道题。
![]()
![]()
考虑到是异或运算求最小cost之和,由于对于二进制,各个位之间是互不影响的,所以可以将问题转会为每个二进制位的求解,然后求和即可。对于每个二进制位,要么为0,要么为1, 就想到将整个图切割成两个点
集,即对于每个点,都只有两种取值,可以看成是要将点集划分成两类。在这种分类思想的指导下,重新考察操作的意义:对于边的两个端点,若它们同类则边权无值;若它们异类则边权有值1。
建一源点S,汇点T
对于已经标号过的点:
1. 对于位为1的点建边 < S, V, INF, 0>
2. 对于位为0的点建边 < V, T, INF, 0>
对于所有的原边
建成流量为1的双向边< u, v, 1, 1>
这样求得最小割,即为当前位的最优解。
这样建边,求最小割时,保证了割边都是原边,求完后,所有与S相连的点可以标号为1, 所有与T相连的边标号为0, 那么这些割边即为相邻点异类的边,同时保证了他们的和最小。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <queue>
#include <iostream>
#include <algorithm>
using namespace std;
const int INF = 0x3f3f3f3f;
const int MaxN = 550;
const int MaxM = 3100;
typedef struct node
{
int u,v;
}Point;
typedef struct Node
{
int v,next,cap;
}edge ;
Point a[MaxM];
edge e[MaxM*10];
int mark[MaxN],vis[MaxN],Ans[MaxN];
int H[MaxN];
int n,m,k,s,t,top;
void AddEdge(int u,int v,int w1,int w2)
{
e[top].v = v; e[top].cap = w1;
e[top].next = H[u]; H[u]= top++;
e[top].v = u; e[top].cap = w2;
e[top].next = H[v]; H[v] = top++;
}
bool BFS()
{
memset(vis,0,sizeof(vis));
queue<int>Q;
vis[s] = 1;
Q.push(s);
while(!Q.empty())
{
int u =Q.front();
Q.pop();
for(int i=H[u];~i;i=e[i].next)
{
if(e[i].cap>0&&!vis[e[i].v])
{
vis[e[i].v] = vis[u]+1;
Q.push(e[i].v);
}
}
}
return vis[t];
}
int DFS(int u,int cap)
{
if(u==t)
{
return cap;
}
int ans = 0;
for(int i=H[u];~i;i=e[i].next)
{
if(e[i].cap>0&&vis[e[i].v]==vis[u]+1)
{
int ant = DFS(e[i].v,min(e[i].cap,cap));
ans += ant;
cap -= ant;
e[i].cap-=ant;
e[i^1].cap+=ant;
if(cap==0)
{
break;
}
}
}
return ans;
}
void Dinic()
{
while(BFS())
{
DFS(s,INF);
}
}
void dfs(int u,int bite)
{
vis[u] = 1;
Ans[u]+=bite;
for(int i = H[u];i!=-1;i=e[i].next)//和S相连都为1
{
if(e[i].cap>0&&!vis[e[i].v])
{
dfs(e[i].v,bite);
}
}
}
void Solve()
{
int bite=1;
memset(Ans,0,sizeof(Ans));
while(1)
{
top = 0;
memset(H,-1,sizeof(H));
for(int i=1;i<=m;i++)
{
AddEdge(a[i].u,a[i].v,1,1);
}
bool flag=false;
for(int i=1;i<=n;i++) //以每一位求一次最小割
{
if(mark[i]!=-1)
{
if(mark[i]>=1)
{
flag=true;
}
if(mark[i]%2)
{
AddEdge(s,i,INF,0);
}
else
{
AddEdge(i,t,INF,0);
}
mark[i]>>=1;
}
}
if(!flag)//都为零的时候算法结束
{
break;
}
Dinic();
memset(vis,0,sizeof(vis));
dfs(s,bite);
bite<<=1;
}
for(int i=1;i<=n;i++)
{
if(i!=1) printf(" ");
printf("%d",Ans[i]);
}
puts("");
}
int main()
{
int T;
scanf("%d",&T);
int u,v,w;
while(T--)
{
scanf("%d %d",&n,&m);
s=0,t=n+1;
for(int i=1;i<=m;i++) scanf("%d %d",&a[i].u,&a[i].v);
scanf("%d",&k);
memset(mark,-1,sizeof(mark));
for(int i=1;i<=k;i++)
{
scanf("%d %d",&u,&w);
mark[u] = w;
}
Solve();
}
return 0;
}
OPTM-Optimal Marks-SPOJ839最小割的更多相关文章
- SPOJ 839 OPTM - Optimal Marks (最小割)(权值扩大,灵活应用除和取模)
http://www.spoj.com/problems/OPTM/ 题意: 给出一张图,点有点权,边有边权 定义一条边的权值为其连接两点的异或和 定义一张图的权值为所有边的权值之和 已知部分点的点权 ...
- SP839 Optimal marks(最小割)
SP839 Optimal marks(最小割) 给你一个无向图G(V,E). 每个顶点都有一个int范围内的整数的标记. 不同的顶点可能有相同的标记.对于边(u,v),我们定义Cost(u,v)= ...
- SPOJ839 Optimal Marks(最小割)
题目大概说给一张图,每个点都有权,边的权等于其两端点权的异或和,现已知几个点的权,为了使所有边的边权和最小,其他点的权值该是多少. 很有意思的一道题,完全看不出和网络流有什么关系. 考虑每个未知的点$ ...
- spoj839 Optimal Marks(最小割,dinic)
题目大意: 给你一个无向图\(G(V,E)\). 每个顶点都有一个int范围内的整数的标记. 不同的顶点可能有相同的标记. 对于边\((u,v)\),我们定义\(Cost(u,v)=mark [u]\ ...
- SPOJ 839 Optimal Marks(最小割的应用)
https://vjudge.net/problem/SPOJ-OPTM 题意: 给出一个无向图G,每个点 v 以一个有界非负整数 lv 作为标号,每条边e=(u,v)的权w定义为该边的两个端点的标号 ...
- 【bzoj2400】Spoj 839 Optimal Marks 网络流最小割
题目描述 定义无向图中的一条边的值为:这条边连接的两个点的值的异或值. 定义一个无向图的值为:这个无向图所有边的值的和. 给你一个有n个结点m条边的无向图.其中的一些点的值是给定的,而其余的点的值由你 ...
- 图论(网络流):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 ...
- Optimal Marks SPOJ - OPTM (按位枚举-最小割)
题意:给一张无向图,每个点有其点权,边(i,j)的cost是\(val_i\ XOR \ val_j\).现在只给出K个点的权值,求如何安排其余的点,使总花费最小. 分析:题目保证权值不超过32位整型 ...
- spoj 839 OPTM - Optimal Marks&&bzoj 2400【最小割】
因为是异或运算,所以考虑对每一位操作.对于所有已知mark的点,mark的当前位为1则连接(s,i,inf),否则连(i,t,inf),然后其他的边按照原图连(u,v,1),(v,u,1),跑最大流求 ...
随机推荐
- shell (check return of each line)and sudoer
shell result from cmdline echo $? if 0 then success ;else failure (shell 执行每部返回值,rm -rf 错误,打包不能覆盖) 解 ...
- (Java) 2014年1月1日减一个月涉及时间与字符的转换
import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; impor ...
- form 提交数组的一些trick
在给服务器传值时form利用 $.post( "/member/member/book/" + event_id, { tickets: tickets, csrf_ppw_tok ...
- 使用 apache2 + `mod_proxy_uwsgi` + uwsgi + upstart 部署
使用 apache2 + mod_proxy_uwsgi + uwsgi + upstart 部署 网上运行 python wsgi 的应用时,大部分的资料都是使用 nginx .uwsgi ,很少资 ...
- 简单的js菜单
<!DOCTYPE html> <html> <head> <title>hovertree</title><base target= ...
- lucence.net+盘古分词
第一步: 添加盘古和lucence的dll引用 第二步: 拷贝Dict文件夹到项目 demo里面是Dictionaries 不过官方建议改成Dict 然后把所有项右击属性 改为“如果较新则复制” 第 ...
- Android四大核心组件之BroadCastReceiver
实验内容 实现BroadCast发送和接受 通过BroadCast传递信息 动态注册和注销BroadCast 实验要求 实现BroadCast发送和接受 通过BroadCast传递信息 动态注册和注销 ...
- Ubuntu Dev Box Setup
Editor VIM Sublime Atom Visual Studio Code SSH Client PAC Manager File Manager Double Commander Imag ...
- 手机app开发:浅谈APP登录方式的优劣
手机app开发公司亿合科技要是给你一个机会设计一款APP,你会用什么方式做这个APP的登录模块?根据APP的业务模型的不同会有不同的设计方法.如果是偏内容型的APP,需要优先展示内容给用户,当用户需要 ...
- C++动态加载DLL调用方法
一.构建DLL路径 char szTmp[_MAX_PATH]; char* szPath = getcwd(szTmp, _MAX_PATH);//获取当前工作目录 //构建dll路径 strc ...