Optimal Marks SPOJ - OPTM
一个无向图,每个点有点权,某些点点权确定了,某些点由你来确定,边权为两个点的异或和,要使边权和最小。
这不是一道按位做最小割的大水题么
非常开心地打了,还非常开心地以为有spj,然后非常开心地Wa了
才发现在边权和最小的条件下还要让点权和最小。
这可咋整啊,难不成要费用流。
然后悄悄搜了下题解发现了巧妙的解决方法,把原来建的图中的边权都扩大10000倍,然后在选1的地方边权再悄悄加上1
把它看成10000和1两条边的话,相当于优先考虑大边最小,大边最小的前提下小边最小,即答案。
//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<queue>
#include<cmath>
#include<set>
#include<map>
#define Formylove return 0
#define For(i,a,b) for(int i=(a);i<=(b);i++)
#define Rep(i,a,b) for(int i=(a);i>=(b);i--)
const int M=*,N=;
typedef long long LL;
typedef double db;
using namespace std;
int n,m,k,qd[N],val[N],ec[M][]; template<typename T>void read(T &x) {
char ch=getchar(); x=; T f=;
while(ch!='-'&&(ch<''||ch>'')) ch=getchar();
if(ch=='-') f=-,ch=getchar();
for(;ch>=''&&ch<='';ch=getchar()) x=x*+ch-''; x*=f;
} struct edge {
int u,v,cap,fl,nx;
edge(){}
edge(int u,int v,int cap,int fl,int nx):u(u),v(v),cap(cap),fl(fl),nx(nx){}
}e[M]; int ecnt=,fir[N];
void add(int u,int v,int cap) {
e[++ecnt]=edge(u,v,cap,,fir[u]); fir[u]=ecnt;
//printf("%d->%d:%d\n",u,v,cap);
e[++ecnt]=edge(v,u,,,fir[v]); fir[v]=ecnt;
} queue<int>que;
int d[N];
void bfs(int s,int t) {
que.push(t);
For(i,,n) d[i]=n;
d[t]=;
while(!que.empty()) {
int x=que.front();
que.pop();
for(int i=fir[x];i;i=e[i].nx) {
int y=e[i].v;
if(d[y]==n&&e[i].cap==) {
d[y]=d[x]+;
que.push(y);
}
}
}
} #define inf 1e9
int p[N];
int calc(int s,int t) {
int fl=inf;
for(int i=t;i!=s;i=e[p[i]].u)
fl=min(fl,e[p[i]].cap-e[p[i]].fl);
for(int i=t;i!=s;i=e[p[i]].u)
e[p[i]].fl+=fl,e[p[i]^].fl-=fl;
return fl;
} int c[N],cur[N];
int isap(int s,int t) {
For(i,,n) c[i]=;
bfs(s,t);
For(i,,n) cur[i]=fir[i],c[d[i]]++;
int rs=;
for(int x=s;d[x]<n;) {
if(x==t) {
rs+=calc(s,t);
x=s;
}
int ok=;
for(int &i=cur[x];i;i=e[i].nx) if(e[i].cap>e[i].fl&&d[e[i].v]+==d[x]) {
ok=; p[x=e[i].v]=i; break;
}
if(!ok) {
int D=n; cur[x]=fir[x];
for(int i=fir[x];i;i=e[i].nx) if(e[i].cap>e[i].fl)
D=min(D,d[e[i].v]+);
if(!(--c[d[x]])) break;
c[d[x]=D]++;
if(x!=s) x=e[p[x]].u;
}
}
return rs;
} void init() {
ecnt=;
memset(fir,,sizeof(fir));
} int vis[N];
void dfs(int x) {
vis[x]=;
for(int i=fir[x];i;i=e[i].nx) if(!vis[e[i].v]&&e[i].cap>e[i].fl)
dfs(e[i].v);
} int main() {
#ifdef ANS
freopen(".in","r",stdin);
freopen(".out","w",stdout);
#endif
int T; read(T);
while(T--) {
read(n); read(m);
For(i,,m) {
read(ec[i][]);
read(ec[i][]);
}
read(k);
For(i,,n) val[i]=,qd[i]=;
For(i,,k) {
int x;
read(x); qd[x]=;
read(val[x]);
}
int s=n+,t=n+;
For(i,,) {
init();
For(j,,n) {
if(qd[j]) {
if(val[j]&(<<i)) {
add(s,j,);
add(j,t,inf);
}
else {
add(s,j,inf);
add(j,t,);
}
}
else {
add(s,j,);
add(j,t,);
}
}
For(j,,m) {
int u=ec[j][],v=ec[j][];
add(u,v,); add(v,u,);
}
n+=;
isap(s,t);
n-=;
memset(vis,,sizeof(vis));
dfs(s);
For(j,,n) if(!vis[j]) val[j]|=(<<i);
}
For(i,,n) printf("%d\n",val[i]);
//printf("%d\n",val[n]);
/*long long ans=0;
for(int i=1;i<=m;i++) {
int u=ec[i][0],v=ec[i][1];
ans+=(val[u]^val[v]);
}
printf("%lld\n",ans);*/
}
Formylove;
}
/*
1
6 7
1 2
2 4
1 3
2 3
4 3
1 5
5 6
4
1 5
3 1
4 7
6 2
*/
Optimal Marks SPOJ - OPTM的更多相关文章
- Optimal Marks SPOJ - OPTM (按位枚举-最小割)
题意:给一张无向图,每个点有其点权,边(i,j)的cost是\(val_i\ XOR \ val_j\).现在只给出K个点的权值,求如何安排其余的点,使总花费最小. 分析:题目保证权值不超过32位整型 ...
- Optimal Marks SPOJ - OPTM(最小割)
传送门 论文<最小割模型在信息学竞赛中的应用>原题 二进制不同位上互不影响,那么就按位跑网络流 每一位上,确定的点值为1的与S连一条容量为INF的有向边.为0的与T连一条容量为INF的有向 ...
- 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 ...
- Optimal Marks SPOJ 839
这题远超其他题非常靠近最小割的实际意义: 割边<=>付出代价<=>决定让两个点的值不相同,边权增加 最小割<=>点的值与s一个阵营的与s相同,与t一个阵营的与t相同 ...
- 图论(网络流):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 ...
- 【bzoj2400】Spoj 839 Optimal Marks 按位最大流
Spoj 839 Optimal Marks Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 908 Solved: 347[Submit][Stat ...
- 【BZOJ2400】Spoj 839 Optimal Marks 最小割
[BZOJ2400]Spoj 839 Optimal Marks Description 定义无向图中的一条边的值为:这条边连接的两个点的值的异或值. 定义一个无向图的值为:这个无向图所有边的值的和. ...
- SP839 Optimal marks(最小割)
SP839 Optimal marks(最小割) 给你一个无向图G(V,E). 每个顶点都有一个int范围内的整数的标记. 不同的顶点可能有相同的标记.对于边(u,v),我们定义Cost(u,v)= ...
随机推荐
- Java中的杂流(闸总)
标准输入输出流 System.in: 标准输入流是InputStream的子类对象,字节输入流,只不过是jvm给定的唯一一个从键盘控制条读入的流. public static final InputS ...
- java静态代理及动态代理(学习示例)
1.接口 public interface Channel { void send(); } 2.实现类(可以为各种不同实现) public class ChannelImpl implements ...
- js 加载验证码
<img id="captchaPic" src="{{captcha_src('math')}}" onclick="this.src='{{ ...
- 第十一次 LL(1)文法的判断,递归下降分析程序
1. 文法 G(S): (1)S -> AB (2)A ->Da|ε (3)B -> cC (4)C -> aADC |ε (5)D -> b|ε 验证文法 G(S)是不 ...
- openFrameworks Download
{ https://openframeworks.cc/zh_cn//download/ } 0.10.1 是最新发布的版本. 这个版本是修改了一些BUG的小版本,与版本 0.10.1100%兼容而且 ...
- javascript基础总结之实例(二)
div的显示和隐藏 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://w ...
- Apache中配置数据库连接池(数据源)
由于基于HTTP协议的Web程序是无状态的,因此,在应用程序中使用JDBC时,每次处理客户端请求都会重新建立数据库链接,如果客户端的请求频繁的话,这将会消耗非常多的资源,因此,在Tomcat中提供了数 ...
- Code::Blocks
Code::Blocks 是一个开放源码的全功能的跨平台C/C++集成开发环境. Code::Blocks是开放源码软件.Code::Blocks由纯粹的C++语言开发完成,它使用了著名的图形界面库w ...
- C++——代码风格
google代码风格 1.使用安全的分配器(allocator),如scoped_ptr,scoped_array 2.测试用的,其他的不能用: 2.1 友元 2.2 C++异常 2.3 RTTI 3 ...
- 【node】---token的原理及使用---【alley】
一.登陆的验证流程 当用户请求登录的时候,如果没有问题,我们在服务端生成一条记录,这个记录里可以说明一下登录的用户是谁,然后把这条记录的 ID 号发送给客户端,客户端收到以后把这个 ID 号存储在 C ...