Problem D: Candy

As a teacher of a kindergarten, you have many things to do during a day, one of which is to allot candies to all children in your class. Today you have N candies for the coming M children. Each child likes different candy, and as a teacher who know them well, you can describe how the child i likes the candy j with a number Aji (Aji = 2 if the child i likes the candy j, or else Aji = 1).

The child i feels happy while ( Cij = 1 if the child i get the candy j, or else Cij = 0). Now your task is to allot the candies in such a way that makes every child happy (of course except you, ^_^).

Input

The first line of the input contains a single integer T (1 <= T <= 10), representing the number of cases that follow.

The first line of each case consists of two integers N and M (1 <= N <= 100000, 1 <= M <= 10), which are the number of candies and the number of children.

There are N lines following, the ith line containing M integers: Ai1, Ai2, Ai3, ..., AiM (1 <= Aij <= 2)

The last line of the case consists of M integers: B1, B2, B3, ..., BM (0 <= Bi <= 1000000000).

Output

For each case, if there is a way to make all children happy, display the word “Yes”. Otherwise, display the word “No”.

Sample Input

2
4 3
1 2 1
2 1 1
1 1 2
1 2 2
3 2 2
1 1
1
2

Sample Output

Yes
No
网络流,主要是建图

分配的时候肯定会优先给每个孩子分配喜欢的糖果,所以先只考虑Aij=2的孩子和糖果(i,j)。

如果Ai,j=2,那么把孩子i向糖果j连一条容量为1的边,再建立源点S,向每个孩子连一条容量为Bi/2的边(因为每个开心值为2的糖果只算1,所以孩子的B值也要先除以2),最后把每个糖果向汇点T连容量为1的边,做一次网络最大流。

假设S到孩子i的流量为fi,说明孩子i已经获得了fi*2点快乐值,还需要Bi-fi*2点,这时候f1+f2+..+fm是总共分出去的糖果数,那么还剩N-(f1+f2+..+fm)个糖果,如果这个数>=sigma(Bi-fi*2),即剩余的糖果数大于等于孩子还需要的总共快乐值,则有解,否则无解

PS:每个孩子平均能吃10000个糖,我真是无限ORZ

以下使用的是刘汝佳白书上的DINIC算法模板做的

#include<iostream>
#include<algorithm>
#include<cstring>
#define size_num 100200
#include<vector>
#include<queue>
#define INF 1e8
using namespace std;
int child[105];
struct Dinic
{
struct Edge{int from,to,cap,flow;};
vector<Edge> edges;
//边表。edges[e]和edges[e+1]互为反向弧,
//注意到e必须是偶数即是大的奇数与比他小的偶数互为反向边,即e与e^1互为反向边
vector<int> G[size_num];
//领接表,G[i][j]表示节点i的第j条边在e数组中的序号
void add_edge(int from,int to,int cap)
{
edges.push_back((Edge){from,to,cap,0});//加入正向边
edges.push_back((Edge){to,from,0,0});//加入反向边
int m=edges.size();
G[from].push_back(m-2);//存的是边的位子
G[to].push_back(m-1);//貌似有一种静态链表的感觉
}
int s,t;//源点编号和汇点编号
bool vis[size_num];//bfs时使用
int d[size_num];//从起点到i的距离
int cur[size_num];//当前弧的下标
void init()
{
edges.clear();
for(int i=0;i<size_num;i++)
G[i].clear();
}
bool bfs()
{
memset(vis,0,sizeof(vis));
queue<int > q;
q.push(s);
d[s]=0;
vis[s]=1;
while(!q.empty())
{
int x=q.front();q.pop();
for(int i=0;i<G[x].size();i++)
{
Edge&e=edges[G[x][i]];
if(!vis[e.to]&&e.cap>e.flow)
{
vis[e.to]=1;
d[e.to]=d[x]+1;
q.push(e.to);
} }
}
return vis[t];
} //dfs
int dfs(int x,int a)
{
if (x==t||a==0) return a;
int flow=0,f;
for(int &i=cur[x];i<G[x].size();i++)//从上次考虑的弧
{
Edge &e=edges[G[x][i]];
if(d[x]+1==d[e.to]&&(f=dfs(e.to,min(a,e.cap-e.flow)))>0)
{
e.flow+=f;//增加正向的流量
edges[G[x][i]^1].flow-=f;//减少反向的流量
flow+=f;
a-=f;
if(a==0) break;
}
} return flow;
}
//
int maxflow(int s,int t)
{
this->s=s;this->t=t;
int flow=0;
while(bfs())
{
memset(cur,0,sizeof(cur));
flow+=dfs(s,INF);
}
return flow;
}
}solve;
void read()
{
solve.init();
int n,m;//糖果数量和孩子的数量
cin>>n>>m;
int s=0,t=1+m+n;
//solve->n=t+1;
//1->m表示孩子,m+1->m+n表示糖果
for(int i=1;i<=n;i++)
{
solve.add_edge(i+m,t,1);
for(int j=1;j<=m;j++)
{
int temp;
cin>>temp;
if(temp==2)
solve.add_edge(j,m+i,1);
}
}
long long sum=0;
for(int i=1;i<=m;i++)
{
cin>>child[i];
sum+=child[i];
solve.add_edge(s,i,child[i]/2);
}
int f=solve.maxflow(s,t);
int yu=n-f;
if(sum<=yu+f*2)
cout<<"Yes\n";
else
cout<<"No\n";
} int main()
{ int T;cin>>T;
while(T--)
read();
return 0;
}

以下是不用vector的代码比较快0.5s上一个是3.07秒


#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm> const int maxn = 100055;
const int maxm = 600005;
const int inf = 0x3f3f3f3f;
struct MaxFlow
{
int net[maxn], gap[maxn], dis[maxn], pre[maxn], cur[maxn];
int siz, n;
std::queue <int> Q;
struct EDGE
{
int v, cap, next;
EDGE(){}
EDGE(int a, int b, int c): v(a), cap(b), next(c){}
}E[maxm<<1];
void init(int _n)//要传入节点数
{
n = _n, siz = 0;
memset(net, -1, sizeof(net));
}
void add_edge(int u, int v, int cap)//加边操作
{
E[siz] = EDGE(v, cap, net[u]);
net[u] = siz++;
E[siz] = EDGE(u, 0, net[v]);
net[v] = siz++;
}
void bfs(int st)//广搜
{
int u, v;
for(int i = 0; i <= n; i++)
dis[i] = n, gap[i] = 0;
gap[0] = 1, dis[st] = 0;
Q.push(st);
while(!Q.empty())
{
u = Q.front();
Q.pop();
for(int i = net[u]; i != -1; i = E[i].next)
{
v = E[i].v;
if(!E[i^1].cap || dis[v] < n)
continue;
dis[v] = dis[u] + 1;
gap[dis[v]]++;
Q.push(v);
}
}
}
int isap(int st, int en)//st 是源点 en 是汇点
{
int u = pre[st] = st, ma = 0, aug = inf, v;
bfs(en);
for(int i = 0; i <= n; i++)
cur[i] = net[i];
while(dis[st] <= n)
{
loop: for(int &i = cur[u]; v = E[i].v, i != -1; i = E[i].next)
if(E[i].cap && dis[u] == dis[v] + 1)
{
aug = std::min(aug, E[i].cap);
pre[v] = u, u = v;
if(v == en)
{
ma += aug;
for(u = pre[u]; v != st; v = u, u = pre[u])
{
E[cur[u]].cap -= aug;
E[cur[u]^1].cap += aug;
}
aug = inf;
}
goto loop;
}
int mi = n;
for(int i = net[u]; v = E[i].v, i != -1; i = E[i].next)
if(E[i].cap && mi > dis[v])
{
cur[u] = i;
mi = dis[v];
}
if(--gap[dis[u]] == 0)
break;
gap[dis[u]=mi+1]++;
u = pre[u];
}
return ma;
}
}; MaxFlow G; int main()
{
int t, n, m, st, en, temp;
long long sum; scanf("%d", &t);
while(t--)
{
scanf("%d %d", &n, &m);
st = 0, en = n + m + 1;
G.init(en);
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
{
scanf("%d", &temp);
if(temp == 2)
G.add_edge(i, j+n, 1);
}
sum = 0;
for(int i = 1; i <= m; i++)
{
scanf("%d", &temp);
sum += temp;
}
for(int i = 1; i <= n; i++)
G.add_edge(st, i, 1);
for(int i = 1; i <= m; i++)
G.add_edge(i+n, en, inf);
if(((long long)n+G.isap(st, en)) >= sum)
puts("Yes");
else
puts("No");
}
return 0;
}



joj 2453 candy 网络流建图的题的更多相关文章

  1. poj 3281 Dining 网络流-最大流-建图的题

    题意很简单:JOHN是一个农场主养了一些奶牛,神奇的是这些个奶牛有不同的品味,只喜欢吃某些食物,喝某些饮料,傻傻的John做了很多食物和饮料,但她不知道可以最多喂饱多少牛,(喂饱当然是有吃有喝才会饱) ...

  2. hdu-4292.food(类dining网络流建图)

    Food Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

  3. [ZJOI2010]贪吃的老鼠(网络流+建图)

    题目描述 奶酪店里最近出现了m只老鼠!它们的目标就是把生产出来的所有奶酪都吃掉.奶酪店中一天会生产n块奶酪,其中第i块的大小为pi,会在第ri秒被生产出来,并且必须在第di秒之前将它吃掉.第j只老鼠吃 ...

  4. 网络流建图(典型)(EK)

    题目链接:https://cn.vjudge.net/contest/68128#problem/B 具体思路: 按照  源点 - > 食物 - > 牛1 - > 牛2 - > ...

  5. POJ 2195 一人一房 最小费用流 建图 水题

    Going Home Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 21010   Accepted: 10614 Desc ...

  6. HDU 4888 Redraw Beautiful Drawings 网络流 建图

    题意: 给定n, m, k 以下n个整数 a[n] 以下m个整数 b[n] 用数字[0,k]构造一个n*m的矩阵 若有唯一解则输出这个矩阵.若有多解输出Not Unique,若无解输出Impossib ...

  7. URAL 1736 Chinese Hockey 网络流+建图

    题目链接:点击打开链接 题意: 给定n个队伍的得分情况,输出随意一个可行解. n个队伍随意2个队伍 a, b 间有且仅有一场比赛. 比赛结果分4种: 1.a +3, b +0 2.a +0, b +3 ...

  8. [SCOI2007]修车(建图好题)

    [SCOI2007]修车 https://www.lydsy.com/JudgeOnline/problem.php?id=1070 Time Limit: 1 Sec  Memory Limit:  ...

  9. HDU 3036 Escape 网格图多人逃生 网络流||二分匹配 建图技巧

    题意: 每一个' . '有一个姑娘, E是出口,'.'是空地 , 'X' 是墙. 每秒钟每一个姑娘能够走一步(上下左右) 每秒钟每一个出口仅仅能出去一个人 给定n*m的地图, 时限T 问全部姑娘是否能 ...

随机推荐

  1. 20160201.CCPP体系详解(0011天)

    内容概要:C语言基本数据类型及运算题库(含答案) 第二章 基本数据类型及运算 一.选择题 1. 若以下选项中的变量已正确定义,则正确的赋值语句是[C]. A) x1=26.8%3; B) 1+2=x2 ...

  2. JAVA规则引擎 -- Drools

    Drools是一个基于java的规则引擎,开源的,可以将复杂多变的规则从硬编码中解放出来,以规则脚本的形式存放在文件中,使得规则的变更不需要修正代码重启机器就可以立即在线上环境生效. 本文所使用的de ...

  3. Singleton模式写法

    public class Singleton { /** * 类级的内部类,也就是静态的成员式内部类,该内部类的实例与外部类的实例 * 没有绑定关系,而且只有被调用到才会装载,从而实现了延迟加载 */ ...

  4. scala学习笔记(4):占位符

    scala 中占位符的用法 1.作为“通配符”,类似Java中的*.如import scala.math._ 2.:_*作为一个整体,告诉编译器你希望将某个参数当作参数序列处理!例如val s = s ...

  5. JVM——新生代与老年代

    首先看在JVM的堆中,按代的划分: Young:主要是用来存放新生的对象. Old:主要存放应用程序中生命周期长的内存对象. Permanent:是指内存的永久保存区域,主要存放Class和Meta的 ...

  6. Android 图文教学让你彻底理解activity启动模式

    我们首先从最简单的开始, standard 这个模式就是默认的模式,我们都知道 当你用这个模式时,每次发送一个intent,都会生成一个新的实例! 我写一个简单的例子: <?xml versio ...

  7. 基于CentOS与VmwareStation10搭建Oracle11G RAC 64集群环境:4.安装Oracle RAC FAQ-4.2.Oracleasm Createdisk ASM磁盘失败:Instantiating disk: failed

    1.错误信息:Instantiating disk: failed [root@linuxrac1 /]# /usr/sbin/oracleasm createdisk OCR_VOTE /dev/s ...

  8. Symfony2学习笔记之数据库操作

    数据库和Doctrine让我们来面对这个对于任何应用程序来说最为普遍最具挑战性的任务,从数据库中读取和持久化数据信息.幸运的是,Symfony和Doctrine进行了集成,Doctrine类库全部目标 ...

  9. 【转】linux下mkisofs制作光盘映像cdrecord刻录光盘

    1.制作光盘映像文件 $mkisofs -R -o /var/tmp/oracle.iso /home/oracle $mkisofs -o myiso.iso /home/oracle/data 补 ...

  10. 如何在Docker中部署DzzOffice

    一.一些背景 之前研究Docker很久了,并且在公司内部实际使用起来了,目前分两种场景使用Docker 1.作为PAAS,提供一致,统一的编译/测试环境: 2.作为虚拟机,直接分配给新来的开发人员使用 ...