传送门:https://www.luogu.org/problemnew/show/P1231

这是一道很不错的网络流入门题,关键在于如何建图。

首先,我们将练习册和源点连一条边权为1的边,然后若书 i 和练习册 j 可以配套,就将连一条从练习册 j 到书 i 边,当然边权还是1。同理,答案和书也是如此,最后再将答案和汇点连一条边权为1的边。

但是这么写还是会有点问题,因为经过一本书的路径可能与很多条,书就被使用了多次,显然不符合题意。这时候我们可以将书 i 拆成书 i1 和 i2,i1 和练习册连边,i2 和答案连边,这样就保证没一本书之用过一次了。

建好图后跑最大流就行了。

 #include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<stack>
#include<queue>
#include<vector>
using namespace std;
#define enter printf("\n")
#define space printf(" ")
#define Mem(a) memset(a, 0, sizeof(a))
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-;
const int maxn = 1e4 + ;
inline ll read()
{
ll ans = ;
char ch = getchar(), last = ' ';
while(!isdigit(ch)) {last = ch; ch = getchar();}
while(isdigit(ch))
{
ans = ans * + ch - ''; ch = getchar();
}
if(last == '-') ans = -ans;
return ans;
}
inline void write(ll x)
{
if(x < ) x = -x, putchar('-');
if(x >= ) write(x / );
putchar(x % + '');
} int t, n1, n2, n3; struct Edge
{
int from, to, cap, flow;
};
vector<Edge> edges;
vector<int> G[maxn << ];
void addEdge(int from, int to)
{
edges.push_back((Edge){from, to, , });
edges.push_back((Edge){to, from, , });
int sz = edges.size();
G[from].push_back(sz - );
G[to].push_back(sz - );
} int dis[maxn << ];
bool vis[maxn << ];
bool bfs()
{
Mem(vis);
queue<int> q;
q.push(); vis[] = ;
dis[] = ;
while(!q.empty())
{
int now = q.front(); q.pop();
for(int i = ; i < (int)G[now].size(); ++i)
{
Edge& e = edges[G[now][i]];
if(!vis[e.to] && e.cap > e.flow)
{
vis[e.to] = ;
dis[e.to] = dis[now] + ;
q.push(e.to);
}
}
}
return vis[t];
}
int cur[maxn << ];
int dfs(int now, int a)
{
if(now == t || !a) return a;
int flow = , f;
for(int& i = cur[now]; i < (int)G[now].size(); ++i)
{
Edge& e = edges[G[now][i]];
if(dis[e.to] == dis[now] + && (f = dfs(e.to, min(a, e.cap - e.flow))) > )
{
e.flow += f;
edges[G[now][i] ^ ].flow -= f;
flow += f; a -= f;
if(!a) break;
}
}
return flow;
} int maxflow()
{
int flow = ;
while(bfs())
{
Mem(cur);
flow += dfs(, INF);
}
return flow;
} //bool vis2[maxn]; int main()
{
n1 = read(); n2 = read(); n3 = read();
t = (n1 << )+ n2 + n3 + ; //为了防止编号重复
/*按注释掉的写法会WA掉,因为如果一本书多次输入,那么这个书
就多次拆点,这一本书就可以使用多次了 */
/* int m = read();
while(m--)
{
int x = read(), y = read();
addEdge(0, y + (n1 << 1));
addEdge(y + (n1 << 1), x);
addEdge(x, x + n1);
vis2[x] = 1;
}
m = read();
while(m--)
{
int x = read(), y = read();
if(!vis2[x]) addEdge(x, x + n1), vis2[x] = 1;
addEdge(x + n1, y + (n1 << 1) + n2);
addEdge(y + (n1 << 1) + n2, t);
}*/
int m = read();
while(m--)
{
int x = read(), y = read();
addEdge(y + (n1 << ), x);
}
m = read();
while(m--)
{
int x = read(), y = read();
addEdge(x + n1, y + (n1 << ) + n2);
}
for(int i = ; i <= n1; ++i) addEdge(i, i + n1);
for(int i = ; i <= n2; ++i) addEdge(, i + (n1 << ));
for(int i = ; i <= n3; ++i) addEdge(i + (n1 << ) + n2, t);
write(maxflow()); enter;
}

P1231 教辅的组成的更多相关文章

  1. Luogu P1231 教辅的组成

    Luogu P1231 教辅的组成 题目背景 滚粗了的HansBug在收拾旧语文书,然而他发现了什么奇妙的东西. 题目描述 蒟蒻HansBug在一本语文书里面发现了一本答案,然而他却明明记得这书应该还 ...

  2. 洛谷 P1231 教辅的组成

    P1231 教辅的组成 题目背景 滚粗了的HansBug在收拾旧语文书,然而他发现了什么奇妙的东西. 题目描述 蒟蒻HansBug在一本语文书里面发现了一本答案,然而他却明明记得这书应该还包含一份练习 ...

  3. 洛谷——P1231 教辅的组成

    P1231 教辅的组成 题目背景 滚粗了的HansBug在收拾旧语文书,然而他发现了什么奇妙的东西. 题目描述 蒟蒻HansBug在一本语文书里面发现了一本答案,然而他却明明记得这书应该还包含一份练习 ...

  4. 【解题报告】洛谷 P1231 教辅的组成

    [解题报告]洛谷 P1231 教辅的组成 题目链接 CSDN链接 这道题就只是一道普通的最大流问题,但是关键所在就是如何构图.要不是我看了题解,真的想不到这个构图方法呢 题目大意我就不写了,自己看好了 ...

  5. P1231 教辅的组成(最大流)

    P1231 教辅的组成 这个题一看便知是网络流量,(三分图??滑稽..) 就一个小细节,如果我们仅仅将所有的点分成三部分跑网络流的话会有点小问题.. 因为这可能导致一本书被重复利用,就是有两条流经过同 ...

  6. 【luogu P1231 教辅的组成】 题解

    题目链接:https://www.luogu.org/problemnew/show/P1231 对于每本书只能用一次,所以拆点再建边 #include <queue> #include ...

  7. 洛谷 P1231 教辅的组成(网络最大流+拆点加源加汇)

    题目背景 滚粗了的HansBug在收拾旧语文书,然而他发现了什么奇妙的东西. 题目描述 蒟蒻HansBug在一本语文书里面发现了一本答案,然而他却明明记得这书应该还包含一份练习题.然而出现在他眼前的书 ...

  8. [洛谷P1231] 教辅的组成

    题目大意:有n1本书,n2本练习册和n3个答案,然后又一些条件,说明某本答案可能和某本书对应,某本练习册可能和某本书对应,求最多有多少本完整的书(有书,练习册,答案) 题解:网络流,对应就连边,然后考 ...

  9. 【Luogu】P1231教辅的组成(拆点+Dinic+当前弧优化)

    题目链接 妈耶 我的图建反了两次 准确的说是有两个地方建反了,然后反上加反改了一个小时…… 知道为什么要拆点吗? 假设这是你的图   左边到右边依次是超级源点    练习册     书     答案 ...

随机推荐

  1. Git使用(一)——Cygwin

    1.下载2.安装镜像:1)上海交大的FTP:ftp://ftp.sjtu.edu.cn/sites/cygwin.com/pub/cygwin/2)163的镜像:http://mirrors.163. ...

  2. Python生成语音

    from aip import AipSpeech # 利用百度语音合成音频文件 """ 你的 APPID AK SK """ APP_ID ...

  3. Spring是什么 包括SpringBean SpringMVC SpringBoot SpringCloud

    什么是Spring:spring是个开源框架,spring mvc是基于spring的一个mvc框架,spring boot是基于spring4的条件注册的一套快速开发整合包. Spring两大特征: ...

  4. 对vector等STL标准容器进行排序操作(转!)

    西方有句谚语:不要重复发明轮子! STL几乎封装了所有的数据结构中的算法,从链表到队列,从向量到堆栈,对hash到二叉树,从搜索到排序,从增加到删除......可以说,如果你理解了STL,你会发现你已 ...

  5. Linux常用基本命令(chmod)

    chmod命令用来改变文件或者目录的权限,只有文件的属主和超级用户才能够执行这个命令 格式: chmod [option] [mode] [file] >常用参数选项 -R : 递归修改目录以及 ...

  6. mysql常用语句练习-基于ecshop2.7.3数据库(1)

    SELECT * FROM ecs_goods WHERE goods_id = 1;SELECT goods_id, goods_name FROM ecs_goods WHERE goods_id ...

  7. AJAX通过HTML请求C#一般处理程序

    AJAX通过HTML请求C#一般处理程序 <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"&g ...

  8. js-ES6学习笔记-Promise对象

    1.Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大. 2.所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作) ...

  9. HTML5 简单归纳 -- 前端知识 (一)

    HTML5简介 1.h5不是一个新语言,它是HTML语言第五次重大修改--版本 2.   2014年  h5 3.支持:目前所有的主流浏览器都支持h5,IE8以下不支持 4.特性: a:抛弃了h4中不 ...

  10. 从零开始学习html(十一)CSS盒模型——下

    六.盒模型--边框(一) <!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type& ...