【解题报告】洛谷 P1231 教辅的组成
【解题报告】洛谷 P1231 教辅的组成
题目链接
CSDN链接
这道题就只是一道普通的最大流问题,但是关键所在就是如何构图。要不是我看了题解,真的想不到这个构图方法呢
题目大意我就不写了,自己看好了。因为我觉得我写得可能还不如你们直接看题目的好
我疑惑的地方
我还没有做过这种有多种搭配的问题,所以我刚开始的构图思路就是:
- 从源点S向所有的书连一条边
- 从书向相关的答案和练习册连一条边
- 从答案和练习册向汇点T连一条边
但是,这么做显然是不对的。
正确的方法
- 把所有的书拆成两个点,我称之为bookstart和bookend
- 从源点S向每一本练习册连一条边,容量为1,表示这本练习册最多只能选一次
- 若练习册u和书v是对应的,从练习册u向vstart连一条容量为1的边,(事实上这里的容量只要大于等于1就可以)表示u和v是对应的。
- 把每一本书的bookstart向bookend连一条容量为一的边,这样就可以限制流过一本书的流量最多为1,表示每一本书最多只能被选一遍。
- 若书u和答案v是对应的,从书uend向v连一条容量为1的边,(事实上这里也是容量大于等于1就可以了,因为流过bookend这个点的流量最多只能是1)表示u和v是对应的
- 所有的答案向汇点连一条容量为1的边,表示这本答案只能被选一次
- 这张图的最大流即为答案所求
图片示意大致如下
感悟
又学会了一种构图方法。但是如果不是只有三类物品,而是有四类或者更多物品的话,我就不知道怎么构图了。
AC代码
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const int INF=100000000;
const int N=50000;
const int M=150000;
int Head[N],Next[M],Edge[M],Ver[M],tot=1;
int D[N];
const int S=40001,T=40002;
void add(int,int,int);
int min(int,int);
int max(int,int);
bool bfs(void);
int dinic(int,int);//我用dinic算法求最大流
int main()
{
//我用Head[1~10000]存book_start
// Head[10001~20000]存练习册
// Head[20001~30000]存答案
// Head[30001~40000]存book_end
//不要问我为什么这么存,我也是随便来的
int n1,n2,n3,m1,m2;
scanf("%d%d%d",&n1,&n2,&n3);
for(int i=1;i<=n2;i++)
add(S,10000+i,1);
for(int i=1;i<=n3;i++)
add(20000+i,T,1);
for(int i=1;i<=n1;i++)
add(i,30000+i,1);
scanf("%d",&m1);
for(int i=1;i<=m1;i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(10000+y,x,1);
}
scanf("%d",&m2);
for(int i=1;i<=m2;i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(30000+x,20000+y,1);
}
int max_flow=0;
while(bfs()) max_flow+=dinic(S,INF);
printf("%d\n",max_flow);
return 0;
}
int dinic(int x,int flow)
{
if(x==T) return flow;
int rest=flow;
for(int p=Head[x];rest&&p;p=Next[p])
{
if(D[Ver[p]]==D[x]+1&&Edge[p])
{
int k=dinic(Ver[p],min(rest,Edge[p]));
if(!k) D[Ver[p]]=0;
Edge[p]-=k;
Edge[p^1]+=k;
rest-=k;
}
}
return flow-rest;
}
bool bfs(void)
{
memset(D,0,sizeof(D));
D[S]=1;
queue <int> q;
q.push(S);
while(!q.empty())
{
int x=q.front();
q.pop();
for(int p=Head[x];p;p=Next[p])
if(!D[Ver[p]]&&Edge[p])
{
D[Ver[p]]=D[x]+1;
if(Ver[p]==T) return 1;
q.push(Ver[p]);
}
}
return 0;
}
void add(int u,int v,int c)
{
Next[++tot]=Head[u],Head[u]=tot,Edge[tot]=c,Ver[tot]=v;
Next[++tot]=Head[v],Head[v]=tot,Edge[tot]=0,Ver[tot]=u;
}
inline int max(int a,int b)
{
return a>b?a:b;
}
inline int min(int a,int b)
{
return a<b?a:b;
}
【解题报告】洛谷 P1231 教辅的组成的更多相关文章
- 洛谷 P1231 教辅的组成
P1231 教辅的组成 题目背景 滚粗了的HansBug在收拾旧语文书,然而他发现了什么奇妙的东西. 题目描述 蒟蒻HansBug在一本语文书里面发现了一本答案,然而他却明明记得这书应该还包含一份练习 ...
- 洛谷——P1231 教辅的组成
P1231 教辅的组成 题目背景 滚粗了的HansBug在收拾旧语文书,然而他发现了什么奇妙的东西. 题目描述 蒟蒻HansBug在一本语文书里面发现了一本答案,然而他却明明记得这书应该还包含一份练习 ...
- 洛谷 P1231 教辅的组成(网络最大流+拆点加源加汇)
题目背景 滚粗了的HansBug在收拾旧语文书,然而他发现了什么奇妙的东西. 题目描述 蒟蒻HansBug在一本语文书里面发现了一本答案,然而他却明明记得这书应该还包含一份练习题.然而出现在他眼前的书 ...
- [洛谷P1231] 教辅的组成
题目大意:有n1本书,n2本练习册和n3个答案,然后又一些条件,说明某本答案可能和某本书对应,某本练习册可能和某本书对应,求最多有多少本完整的书(有书,练习册,答案) 题解:网络流,对应就连边,然后考 ...
- 洛谷P1231 教辅的组成 最大流
裸题… Code: #include<cstdio> #include<cstring> #include<algorithm> #include<vecto ...
- 洛谷P1231 教辅的组成 网络流
Code: #include<cstdio> #include<cstring> #include<algorithm> #include<vector> ...
- 洛谷 P1231教辅的组成
题目描述 /* s->练习册(1~b)->书(b+1~a+b)->答案(a+b+1~a+b+c)->t 但是可能会有多本练习册指向同一本书,这本书又可能会指向多本答案 这样每本 ...
- 「洛谷P1231」教辅的组成 解题报告
P1231 教辅的组成 题目背景 滚粗了的HansBug在收拾旧语文书,然而他发现了什么奇妙的东西. 题目描述 蒟蒻HansBug在一本语文书里面发现了一本答案,然而他却明明记得这书应该还包含一份练习 ...
- AC日记——教辅的组成 洛谷 P1231
题目背景 滚粗了的HansBug在收拾旧语文书,然而他发现了什么奇妙的东西. 题目描述 蒟蒻HansBug在一本语文书里面发现了一本答案,然而他却明明记得这书应该还包含一份练习题.然而出现在他眼前的书 ...
随机推荐
- POJ-3268-最短路(dijkstra算法)
Silver Cow Party Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 12494 Accepted: 5568 ...
- java学习总结——你的前世今生
一.背景 JAVA语言最開始仅仅是Sun电脑(Sun MicroSystems)公司在1990年12月開始研究的一个内部项目. Sun电脑公司的一个叫做帕特里克·诺顿的project师被公司自己开发的 ...
- android自己定义控件系列教程-----仿新版优酷评论剧集卡片滑动控件
我们先来看看优酷的控件是怎么回事? 仅仅响应最后也就是最顶部的卡片的点击事件,假设点击的不是最顶部的卡片那么就先把它放到最顶部.然后在移动到最前面来.重复如次. 知道了这几条那么我们就非常好做了. 里 ...
- CSS自适应宽度的高级应用,一般人不会告诉你。
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAxgAAACdCAIAAAC4iknFAAAgAElEQVR4nO2d3VsTV7uH51/wqhKotn
- ubuntu多版本jdk安装及切换
系统:ubuntu14.04 一.安装openjdk1.7 sudo apt-get install openjdk-7-jre openjdk-7-jdk 安装完成后找到其安装路径: dpkg -L ...
- Caused by: java.lang.NullPointerException: Attempt to write to field 'int android.app.Fragment.mNextAnim' on a null object reference
原因fragment必须先add(),才能remove(),故remove前先做判空操作 参考:http://www.cnblogs.com/hixin/p/4427276.html
- 39. Ext.data.SimpleStore的使用方法
转自:https://www.cnblogs.com/bluestorm/archive/2013/06/14/3135361.html 新版4.2的extjs已经废弃了simpleStore --& ...
- Sort List 典型链表
https://leetcode.com/problems/sort-list/ Sort a linked list in O(n log n) time using constant space ...
- 学学cookie和session
什么是Cookie? HTTP Cookie(也叫 Web Cookie或浏览器 Cookie)是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器下次向同一服务器发起请求时被携带并发送到服 ...
- target属性打开方式
在HTML中target目标的四个参数的用法:1.target="_self"表示:将链接的画面内容,显示在目前的视窗中.(内定值) . 即:同(自己)窗口打开,别的数据还存在,相 ...