codeforces gym 100357 I (费用流)
题目大意

给出一个或与表达式,每个正变量和反变量最多出现一次,询问是否存在一种方案使得每个或式中有且仅有一个变量的值为1。
解题分析
将每个变量拆成三个点x,y,z。 y表示对应的正变量,z表示对应的反变量。
由S向每个点的x部连一条流量为1的边,表示该变量的某个正变量或反变量的取值为1。
由每个点的x部向y部和z部分别连一条流量为1的边,表示每个正变量和反变量仅有一个取值为1。
若某个或式中含有某个变量,则由该变量的y部或z部向或式连一条流量为1的边。表示该变量可以使该或式的结果为1。
由每个或式向T连一条流量为1的边,表示该或式被满足,且仅有一个变量的取值为1。
仅仅这么连还是不够的,因为如果某个变量的正变量和反变量同时出现,那么正变量或反变量中必定有一个值为1,对应到图上则是S向该变量的x部必须有1的流量。
所以可以向这条边添加上-1的费用,使得该变量的值优先被满足。
跑一遍最小费用最大流,如果是满流且费用的绝对值等于必须被确定值的变量的数量,则说明可以成功满足。
输出方案时只需遍历一下残余网络中的边,如果残余网络中没有流量则说明该变量被选择了,最后注意一下细节,确定一下对于每个变量选1还是选0。
参考程序
#include <bits/stdc++.h>
using namespace std; #define rep(i,x,y) for (int i=x;i<=y;i++)
const int N=;
const int INF=; int n,m,S,T,sum,minC,maxF;
int lt[N*],flag[N],dis[N*],pd[N*],pre[N*],sgn[N*];
vector <int> vec[N]; struct edge{
int u,v,f,w,nt;
}eg[N*]; void add(int u,int v,int f,int w)
{
//cout<<u<<" "<<v<<" "<<f<<" "<<w<<endl;
eg[++sum]=(edge){u,v,f,w,lt[u]}; lt[u]=sum;
eg[++sum]=(edge){v,u,,-w,lt[v]}; lt[v]=sum;
} bool spfa()
{
queue <int> Q;
rep (i,S,T) dis[i]=INF,pd[i]=,pre[i]=-;
dis[S]=; pd[S]=; Q.push(S);
while (!Q.empty())
{
int u=Q.front();
for (int i=lt[u];i;i=eg[i].nt)
{
int v=eg[i].v;
if (eg[i].f>)
{
if (dis[u]+eg[i].w<dis[v])
{
dis[v]=dis[u]+eg[i].w;
pre[v]=i;
if (!pd[v])
{
Q.push(v);
pd[v]=;
}
}
}
}
pd[u]=; Q.pop();
}
return dis[T]!=INF;
}
void minCmaxF()
{
int flow;
while (spfa())
{
flow=INF;
for (int i=pre[T];~i;i=pre[eg[i].u])
flow=min(flow,eg[i].f);
for (int i=pre[T];~i;i=pre[eg[i].u])
eg[i].f-=flow,eg[i^].f+=flow;
maxF+=flow;
minC+=flow*dis[T];
}
} int main()
{
freopen("sat.in","r",stdin);
freopen("sat.out","w",stdout); cin.sync_with_stdio();
sum=; memset(lt,,sizeof(lt));
int limit=; cin>>n>>m;
S=; T=*n+m+;
rep(i,,m)
{
int num; cin>>num;
rep(j,,num)
{
int x; cin>>x;
flag[abs(x)]++;
if (x>) sgn[x]=; else sgn[x]=-;
vec[i].push_back(x);
}
}
rep(i,,n) if (flag[i]==) add(S,i,,-),limit++; else add(S,i,,);
rep(i,,n) {add(i,n+*i-,,); add(i,n+*i,,);}
rep(i,,m)
{
for (auto v:vec[i])
{
int x=v>?n+*abs(v)-:n+*abs(v);
add(x,n*+i,,);
}
add(*n+i,T,,);
}
minC=maxF=;
minCmaxF();
vector <int> ans;
if (minC==-limit && maxF==m)
{
cout<<"YES"<<endl;
for (int i=lt[S];i;i=eg[i].nt)
{
if (eg[i].f==)
{
if (sgn[eg[i].v]==) ans.push_back(); else ans.push_back();
}
else
{
if (eg[lt[eg[i].v]].f==) ans.push_back(); else ans.push_back();
}
}
for (int i=ans.size()-;i>=;i--) cout<<ans[i]<<" ";
cout<<endl;
}
else cout<<"NO"<<endl;
}

codeforces gym 100357 I (费用流)的更多相关文章
- CodeForces 164C Machine Programming 费用流
Machine Programming 题目连接: http://codeforces.com/problemset/problem/164/B Descriptionww.co One remark ...
- Codeforces 708D 上下界费用流
给你一个网络流的图 图中可能会有流量不平衡和流量>容量的情况存在 每调整一单位的流量/容量 需要一个单位的花费 问最少需要多少花费使得原图调整为正确(可行)的网络流 设当前边信息为(u,v,f, ...
- CodeForces 1187G Gang Up 费用流
题解: 先按时间轴将一个点拆成100个点. 第一个点相当于第一秒, 第二个点相当于第二秒. 在这些点之间连边, 每1流量的费用为c. 再将图上的边也拆开. 将 u_i 向 v_i+1 建边. 将 v_ ...
- codeforces gym 100357 J (网络流)
题目大意 有n种物品,m种建筑,p个人. n,m,p∈[1,20] 每种建筑需要若干个若干种物品来建造.每个人打算建造一种建筑,拥有一些物品. 主角需要通过交易来建造自己的建筑,交易的前提是对方用多余 ...
- codeforces gym 100357 H (DP 高精度)
题目大意 有r*s张扑克牌,数字从1到 r,每种数字有s种颜色. 询问对于所有随机的d张牌,能选出c张组成顺子的概率和组成同花的概率. 解题分析 对于组成顺子的概率,令dp[i][j][k]表示一共选 ...
- codeforces gym 100357 K (表达式 模拟)
题目大意 将一个含有+,-,^,()的表达式按照运算顺序转换成树状的形式. 解题分析 用递归的方式来处理表达式,首先直接去掉两边的括号(如果不止一对全部去光),然后找出不在括号内且优先级最低的符号.如 ...
- Gym - 101492I 区间限制费用流
https://cn.vjudge.net/problem/Gym-101492I 如果用单个点代表每个区间 利用拆点来限制区间的流量的话 点是 n^2/2+m个 边是2*n^2条 但是这样会T 解法 ...
- Codeforces Gym 100002 E "Evacuation Plan" 费用流
"Evacuation Plan" Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/10 ...
- Codeforces Gym 101190M Mole Tunnels - 费用流
题目传送门 传送门 题目大意 $m$只鼹鼠有$n$个巢穴,$n - 1$条长度为$1$的通道将它们连通且第$i(i > 1)$个巢穴与第$\left\lfloor \frac{i}{2}\rig ...
随机推荐
- 规范化创建一个vs2017 Mvc框架项目
vs2107 + dapper + MiniUi 标准化分层封装使 3.1 规范化创建一个vs2017 Mvc框架项目 此时创建的项目勾选 添加单元测试. 添加一个类库,主要用于实体类操作,类库名称 ...
- Windows8.1查看已连接无线WIFI密码
Windows8.1操作系统下查看已连接无线wifi密码操作步骤如下: 1.右键任务栏中的无线图标,在弹出的菜单中选择"打开网络和共享中心": 2.在网络和共享中心界面中点击&qu ...
- Android 性能优化(3)性能工具之「调试 GPU 过度绘制」Debug GPU Overdraw Walkthrough-查看哪些view过度绘制了
Debug GPU Overdraw Walkthrough 1.In this document Prerequisites Visualizing Overdraw You should also ...
- LN : leetcode 399 Evaluate Division
lc 399 Evaluate Division 399 Evaluate Division Equations are given in the format A / B = k, where A ...
- 微信小程序打卡第五天
2018-02-1823:55:53大年初三 微信小程序已经学了5个夜晚了,没有很努力,只是简单地接触,感觉从今天开始有了突破的进展,很爽! 无意间发现一个很好的教程,也是一个老哥分享的,很给力 ht ...
- [权威指南]学习笔记——第1、2章 MongoDB介绍和基础知识
安装目录:C:\Program Files\MongoDB\Server\3.2 Bin:..\..\Program Files\MongoDB\Server\3.2\bin 启动命令:mongod ...
- HDU_2079_(01背包)(dfs)
选课时间(题目已修改,注意读题) Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- Crash (computing)
In computing, a crash (or system crash) occurs when a computer program, such as a software applicati ...
- Oracle 把一个用户所有表的读权限授予另一个用户
create user <USER_NAME> identified by <PASSWORD>; grant create session TO <USER_NAME& ...
- HDU多校Round 1
Solved:5 rank:172 A.Maximum Multiple #include <stdio.h> #include <algorithm> #include &l ...