题链:

http://poj.org/problem?id=2125

题解:

最小割 + 输出割方案。
建图:
拆点,每个题拆为 i 和 i'分别表示其的入点和出点
建立超源 S和超汇 T。
S -> i :(outi[i]) 割了这个边相当于选择了 i-
i'-> T :(ini[i])  割了这个边相当于选择了 i+
u -> v':(INF)
然后求Dinic跑最大流求最小割。

至于求方案,首先显然割的边都和 S或 T相连。
从 S开始沿着非满载的边(包括反向边)dfs,对遇到的点打标记。
如果某个入点 i 没有被标记过,则输出 i -
如果某个出点 i'被标记过,则输出 i +

代码:

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#define MAXN 500
#define MAXM 150000
#define INF 0x3f3f3f3f
using namespace std;
struct Edge{
int to[MAXM],cap[MAXM],nxt[MAXM],head[MAXN],ent;
void Init(){
ent=2;
memset(head,0,sizeof(head));
}
void Adde(int u,int v,int w){
to[ent]=v; cap[ent]=w; nxt[ent]=head[u]; head[u]=ent++;
to[ent]=u; cap[ent]=0; nxt[ent]=head[v]; head[v]=ent++;
}
int Next(int i,bool type){
return type?head[i]:nxt[i];
}
}E;
int cur[MAXN],d[MAXN],mark[MAXN];
int N,M,S,T;
int idx(int i,int k){
return i+k*N;
}
bool bfs(){
queue<int>q;
memset(d,0,sizeof(d));
d[S]=1; q.push(S); int u,v;
while(!q.empty()){
u=q.front(); q.pop();
for(int i=E.Next(u,1);i;i=E.Next(i,0)){
v=E.to[i];
if(d[v]||!E.cap[i]) continue;
d[v]=d[u]+1; q.push(v);
}
}
return d[T];
}
int dfs(int u,int reflow){
if(u==T||!reflow) return reflow;
int flowout=0,f,v;
for(int &i=cur[u];i;i=E.Next(i,0)){
v=E.to[i];
if(d[v]!=d[u]+1) continue;
f=dfs(v,min(reflow,E.cap[i]));
flowout+=f; E.cap[i^1]+=f;
reflow-=f; E.cap[i]-=f;
if(!reflow) break;
}
if(!flowout) d[u]=0;
return flowout;
}
int Dinic(){
int flow=0;
while(bfs()){
memcpy(cur,E.head,sizeof(E.head));
flow+=dfs(S,INF);
}
return flow;
}
void DFS(int u){
mark[u]=1;
for(int i=E.Next(u,1);i;i=E.Next(i,0)){
if(!E.cap[i]||mark[E.to[i]]) continue;
DFS(E.to[i]);
}
}
int main()
{
while(~scanf("%d%d",&N,&M)){
memset(mark,0,sizeof(mark));
S=2*N+1; T=2*N+2; E.Init();
for(int i=1,x;i<=N;i++)
scanf("%d",&x),E.Adde(idx(i,1),T,x);
for(int i=1,x;i<=N;i++)
scanf("%d",&x),E.Adde(S,idx(i,0),x);
for(int i=1,u,v;i<=M;i++)
scanf("%d%d",&u,&v),E.Adde(idx(u,0),idx(v,1),INF);
int ans=Dinic(),num=0;
printf("%d\n",ans);
DFS(S);
for(int i=1;i<=N;i++)
num+=((!mark[i])+(mark[i+N]));
printf("%d\n",num);
for(int i=1;i<=N;i++) {
if(!mark[i])printf("%d -\n",i);
if(mark[i+N])printf("%d +\n",i);
}
}
return 0;
}

最新文章

  1. python 爬虫(二)
  2. iOS 里面 Swift与Objective-C混编,Swift与C++混编的一些比较
  3. JavaScript基础——添加错误处理
  4. 五、mysql存储引擎
  5. lua5.3调用C/C++
  6. (四)JS学习笔记 - 模式 - 观察者模式
  7. 关于在同一母版页中使用多个CSS文件的解决方案
  8. spring项目log4j使用入门
  9. Nginx Rewrite规则详解
  10. 为什么覆写equals必须要覆写hashCode?
  11. springBoot 搭建web项目(前后端分离,附项目源代码地址)
  12. 002.Oracle安装部署-ASM
  13. Java相关文章
  14. 装饰者模式——Java设计模式
  15. netdata的安装与使用
  16. 山寨一个std::bind\boost::bind
  17. opencv学习笔记——FileStorage类的数据存取操作
  18. CodeForces 24A Ring road(dfs)
  19. 什么是ZooKeeper(一)(通俗易懂)
  20. 线性期望(BUPT2015校赛.F)

热门文章

  1. 冲刺NO.12
  2. 【Swift】Runtime动态性分析
  3. c/cpp语言链表连接部分详解
  4. MySQL-压缩版-windows安装
  5. Huginn实现自动通过slack推送豆瓣高分电影
  6. java图片处理开源框架
  7. 解决IE8下opacity属性失效问题
  8. api-gateway实践(13)新服务网关 - 断路保护/熔断机制
  9. Android P专区免费开放 -- 同样的Android,不同的体验
  10. Python之递归函数