题目大意

 

  给出一个或与表达式,每个正变量和反变量最多出现一次,询问是否存在一种方案使得每个或式中有且仅有一个变量的值为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 (费用流)的更多相关文章

  1. CodeForces 164C Machine Programming 费用流

    Machine Programming 题目连接: http://codeforces.com/problemset/problem/164/B Descriptionww.co One remark ...

  2. Codeforces 708D 上下界费用流

    给你一个网络流的图 图中可能会有流量不平衡和流量>容量的情况存在 每调整一单位的流量/容量 需要一个单位的花费 问最少需要多少花费使得原图调整为正确(可行)的网络流 设当前边信息为(u,v,f, ...

  3. CodeForces 1187G Gang Up 费用流

    题解: 先按时间轴将一个点拆成100个点. 第一个点相当于第一秒, 第二个点相当于第二秒. 在这些点之间连边, 每1流量的费用为c. 再将图上的边也拆开. 将 u_i 向 v_i+1 建边. 将 v_ ...

  4. codeforces gym 100357 J (网络流)

    题目大意 有n种物品,m种建筑,p个人. n,m,p∈[1,20] 每种建筑需要若干个若干种物品来建造.每个人打算建造一种建筑,拥有一些物品. 主角需要通过交易来建造自己的建筑,交易的前提是对方用多余 ...

  5. codeforces gym 100357 H (DP 高精度)

    题目大意 有r*s张扑克牌,数字从1到 r,每种数字有s种颜色. 询问对于所有随机的d张牌,能选出c张组成顺子的概率和组成同花的概率. 解题分析 对于组成顺子的概率,令dp[i][j][k]表示一共选 ...

  6. codeforces gym 100357 K (表达式 模拟)

    题目大意 将一个含有+,-,^,()的表达式按照运算顺序转换成树状的形式. 解题分析 用递归的方式来处理表达式,首先直接去掉两边的括号(如果不止一对全部去光),然后找出不在括号内且优先级最低的符号.如 ...

  7. Gym - 101492I 区间限制费用流

    https://cn.vjudge.net/problem/Gym-101492I 如果用单个点代表每个区间 利用拆点来限制区间的流量的话 点是 n^2/2+m个 边是2*n^2条 但是这样会T 解法 ...

  8. Codeforces Gym 100002 E "Evacuation Plan" 费用流

    "Evacuation Plan" Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/10 ...

  9. Codeforces Gym 101190M Mole Tunnels - 费用流

    题目传送门 传送门 题目大意 $m$只鼹鼠有$n$个巢穴,$n - 1$条长度为$1$的通道将它们连通且第$i(i > 1)$个巢穴与第$\left\lfloor \frac{i}{2}\rig ...

随机推荐

  1. Python基础类型(一) int 整型

    Python算术运算符 以下假设变量: a=10,b=20: 运算符 描述 实例 + 加 - 两个对象相加 a + b 输出结果 30 - 减 - 得到负数或是一个数减去另一个数 a - b 输出结果 ...

  2. Linux 搭建Discuz论坛

    title: Linux 搭建Discuz论坛 Welcome to Fofade's Blog! 这里是Linux 搭建论坛的一些命令记录 命令摘记: 下载文件:Discuz 安装环境:PHP Ap ...

  3. ASP.Net 知识点总结(五)

    1.传入某个属性的set方法的隐含参数的名称是什么?value,它的类型和属性所声名的类型相同.2.如何在C#中实现继承? 在类名后加上一个冒号,再加上基类的名称.3.C#支持多重继承么? 不支持.可 ...

  4. 【js】JavaScript parser实现浅析

    最近笔者的团队迁移了webpack2,在迁移过程中,笔者发现webpack2中有相当多的兼容代码,虽然外界有很多声音一直在质疑作者为什么要破坏性更新,其实大家也都知道webpack1那种过于“灵活”的 ...

  5. Linux重启和关机命令

    Linux重启命令: 方式1:shutdown –r now 方式2:reboot Linux关机命令: shutdown –h now

  6. 297 Serialize and Deserialize Binary Tree 二叉树的序列化与反序列化

    序列化是将一个数据结构或者对象转换为连续的比特位的操作,进而可以将转换后的数据存储在一个文件或者内存中,同时也可以通过网络传输到另一个计算机环境,采取相反方式重构得到原数据.请设计一个算法来实现二叉树 ...

  7. WCF wsdlexception(at/html):faultCode=INVALID_WSDL

    WCF 部署正常,通过浏览器查看服务也OK,但是通过SOAP UI创建客户端请求时就异常: wsdlexception(at/html):faultCode=INVALID_WSDL: Expecte ...

  8. MySQL客户端导入数据库脚本,字段值出现乱码解决方法

    解决方法1:在MySql安装目录下找到my.ini,将[mysql]下的default-character-set=latin1改为default-character-set=utf8,保存,然后重启 ...

  9. php angular/think angular/php模版引擎

    在thinphp5中发现一个好用的模版引擎—think-angular, 此模板引擎主要特点是 不需要额外的标签定义, 全部使用属性定义, 写好的模板文件在IDE格式化代码的时候很整洁, 因为套完的模 ...

  10. vuex理解之modules小记

    好记性不如烂笔头 demo预览 源代码 前情提要 关于vuex,其实很久以前就研究使用过,还研究过 flux,redux之类的体系,当时感觉对于 state,action,dispatch,views ...