SPOJ OPTM Optimal Marks

Optimal Marks

Time Limit: 6000ms

Memory Limit: 262144KB

This problem will be judged on SPOJ. Original ID: OPTM
64-bit integer IO format: %lld      Java class name: Main

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

Source

Guo HuaYang

解题:amber同学的paper上面有的经典最小割题目

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 const int INF = ~0U>>2;
  4 const int maxn = 510;
  5 struct arc{
  6     int to,flow,next;
  7     arc(int x = 0,int y = 0,int z = -1){
  8         to = x;
  9         flow = y;
 10         next = z;
 11     }
 12 }e[maxn*maxn];
 13 int head[maxn],gap[maxn],d[maxn],S,T,tot;
 14 void add(int u,int v,int flow){
 15     e[tot] = arc(v,flow,head[u]);
 16     head[u] = tot++;
 17     e[tot] = arc(u,0,head[v]);
 18     head[v] = tot++;
 19 }
 20 void bfs(){
 21     queue<int>q;
 22     memset(gap,0,sizeof gap);
 23     memset(d,-1,sizeof d);
 24     q.push(T);
 25     d[T] = 0;
 26     while(!q.empty()){
 27         int u = q.front();
 28         q.pop();
 29         ++gap[d[u]];
 30         for(int i = head[u]; ~i; i = e[i].next){
 31             if(e[i^1].flow && d[e[i].to] == -1){
 32                 d[e[i].to] = d[u] + 1;
 33                 q.push(e[i].to);
 34             }
 35         }
 36     }
 37 }
 38 int sap(int u,int low){
 39     if(u == T) return low;
 40     int tmp = 0,a,minH = T - 1;
 41     for(int i = head[u]; ~i; i = e[i].next){
 42         if(e[i].flow){
 43             if(d[u] == d[e[i].to] + 1){
 44                 a = sap(e[i].to,min(low,e[i].flow));
 45                 if(!a) continue;
 46                 e[i].flow -= a;
 47                 e[i^1].flow += a;
 48                 low -= a;
 49                 tmp += a;
 50                 if(!low) break;
 51             }
 52             minH = min(minH,d[e[i].to]);
 53             if(d[S] >= T) return tmp;
 54         }
 55     }
 56     if(!tmp){
 57         if(--gap[d[u]] == 0) d[S] = T;
 58         ++gap[d[u] = minH + 1];
 59     }
 60     return tmp;
 61 }
 62 int maxflow(int ret = 0){
 63     bfs();
 64     while(d[S] < T) ret += sap(S,INF);
 65     return ret;
 66 }
 67 int n,m,k,mark[maxn],con[maxn];
 68 bool mp[maxn][maxn],vis[maxn];
 69 void build(int x){
 70     S = n + 1;
 71     T = S + 1;
 72     memset(head,-1,sizeof head);
 73     memset(vis,false,sizeof vis);
 74     tot = 0;
 75     for(int i = 0; i < k; ++i){
 76         if((mark[con[i]]>>x)&1) add(S,con[i],INF);
 77         else add(con[i],T,INF);
 78     }
 79     for(int i = 1; i <= n; ++i)
 80         for(int j = 1; j <= n; ++j)
 81             if(mp[i][j]) add(i,j,1);
 82 }
 83 void dfs(int u,int x){
 84     vis[u] = true;
 85     mark[u] |= (1<<x);
 86     for(int i = head[u]; ~i; i = e[i].next)
 87         if(!vis[e[i].to] && e[i].flow) dfs(e[i].to,x);
 88 }
 89 int main(){
 90     int kase,u,v;
 91     scanf("%d",&kase);
 92     while(kase--){
 93         scanf("%d%d",&n,&m);
 94         memset(mark,0,sizeof mark);
 95         memset(mp,false,sizeof mp);
 96         for(int i = 0; i < m; ++i){
 97             scanf("%d%d",&u,&v);
 98             mp[u][v] = mp[v][u] = true;
 99         }
100         scanf("%d",&k);
101         for(int i = 0; i < k; ++i){
102             scanf("%d%d",&u,&v);
103             mark[u] = v;
104             con[i] = u;
105         }
106         for(int i = 0; i < 32; ++i){
107             build(i);
108             maxflow();
109             dfs(S,i);
110         }
111         for(int i = 1; i <= n; ++i)
112             printf("%d\n",mark[i]);
113     }
114     return 0;
115 }

时间: 2024-12-05 19:33:43

SPOJ 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 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

SPOJ 839 Optimal Marks 最小割 经典 按位建图

胡伯涛论文中的一题,经典建模,由于二进制每一位异或不会相互影响,所以我们把问题转换模型,按位处理. 即已知一些点的标号0/1(还有些可以自己任意改),和一些边,边权定义为两端点标号的异或,要求边权和最小的标号方案. 我们联想到最小割求的是从源到汇容量最小的边权和. 建图: 标号为1的和源点相连,容量INF,标号为0的和汇点相连,容量INF,这些边是不能割掉的(这些点标号已经明确) 原图相连的边,连边,容量为1.(若将此边割掉,则两端点一个为0,一个为1,割为1) 跑完最大流后,在残量网络中dfs

BZOJ2400 Spoj 839 Optimal Marks

首先发现每一位二进制可以分开来做. 然后就变成0.1两种数了,考虑最小割. 设S表示选0,T表示选1,则 对于确定的点向数字对应的S/T连边,边权inf:然后原来图中有边的,互相连边,边权为1. 直接最小割即可,最后还要dfs一下来求出每个未确定的数选的是0还是1. 1 /************************************************************** 2 Problem: 2400 3 User: rausen 4 Language: C++ 5 R

SPOJ839 OPTM - Optimal Marks

传送门 闵神讲网络流应用的例题,来水一水 要写出这道题,需要深入理解两个概念,异或和最小割. 异或具有相对独立性,所以我们把每一位拆开来看,即做大概$32$次最小割.然后累加即可. 然后是最小割把一张图分割成两个集合,简单看就是0集合和1集合. 简单的建图: 原图不变,改成双向边,所有的流量限制为1.然后所有S点向点权为1的连边,点权为0的向T连边,容量都是正无穷. 为什么这样建?首先看,最小割把一张图分成两个点集.而因为我们的流量限制可以让最小割只割真实存在的边,而割的也只有可能是跨越0集合和

SPOJ Optimal Marks(最小割的应用)

SPOJ Optimal Marks(最小割的应用) 真心好题,网络流简直无处不在,能够解决一些看似困难的问题,希望能从中学到其精髓--模型建立+建图 题意: 给定一个无向图,每个顶点都有对应值,每条边的权值为val[u] ^ val[u],同时已知其中某些点的值,求其他点的权值使得最终的图的边权和最小? 分析: 首先边与边之间异或操作,不太好直接处理,因为异或操作每一位运算相互独立,我们来逐位考虑,那么对于那些还未知的权值的点,这一位要么为0 ,要么为1,同时我们还得注意边的两个端点值相同则没

[SPOJ839]Optimal Marks

[SPOJ839]Optimal Marks 试题描述 You are given an undirected graph \(G(V, E)\). Each vertex has a mark which is an integer from the range \([0..2^{31} - 1]\). Different vertexes may have the same mark. For an edge \((u, v)\), we define \(Cost(u, v) = mark

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个子

SPOJ839 Optimal Marks(最小割)

题目大概说给一张图,每个点都有权,边的权等于其两端点权的异或和,现已知几个点的权,为了使所有边的边权和最小,其他点的权值该是多少. 很有意思的一道题,完全看不出和网络流有什么关系. 考虑每个未知的点$x$的权的二进制的第$i$位$x_i$,其对边权和的贡献为$\sum_{(x,y)\in E}(2^i\cdot(x_i\ \hat{}\ y_i))=2^i\sum_{(x,y)\in E}(x_i\ \hat{}\ y_i)$,而$x_i$取值是$0$或$1$! 这样问题就明了了: 相当于对于每

BZOJ 2400 Optimal Marks 最小割

题目大意:给定一个无向图,一些点有权值,其它点的权值可以自己指定,要求指定这些点的权值,使每条边两边的点权异或值之和最小 在此基础上要求点权和最小 首先不考虑点权和最小这个条件 那么我们将每一位分开计算 我们会发现这是一个最小割的模型 令S集为0,T集为1,如果这个点的点权已经指定,则向相应集合连流量为INF的边 每条边的两端点之间连一条流量为1的边 跑最小割就是答案 现在我们将点权考虑进去 将原图每条边的流量扩大10000倍 如果一个点和S没有连边,就从S向这个点连一条流量为1的边 这样如果和