[kuangbin带你飞]专题十一 网络流
2016-04-06 19:05
525 查看
ID | Origin | Title | ||
---|---|---|---|---|
34 / 81 | Problem A | POJ 3436 | ACM Computer Factory | |
92 / 195 | Problem B | POJ 3281 | Dining | |
55 / 148 | Problem C | POJ 1087 | A Plug for UNIX | |
59 / 111 | Problem D | POJ 2195 | Going Home | |
44 / 132 | Problem E | POJ 2516 | Minimum Cost | |
35 / 72 | Problem F | POJ 1459 | Power Network | |
40 / 217 | Problem G | HDU 4280 | Island Transport | |
42 / 133 | Problem H | HDU 4292 | Food | |
34 / 90 | Problem I | HDU 4289 | Control | |
28 / 90 | Problem J | UVA 10480 | Sabotage | |
19 / 37 | Problem K | HDU 2732 | Leapin' Lizards | |
13 / 136 | Problem L | HDU 3338 | Kakuro Extension | |
36 / 358 | Problem M | HDU 3605 | Escape | |
17 / 58 | Problem N | HDU 3081 | Marriage Match II | |
15 / 61 | Problem O | HDU 3416 | Marriage Match IV |
没懂。。
此题是最大流问题。题目意思比较难懂。
看得比较纠结。
就是说有N台组装电脑的机器。电脑的组成部分共有P部分。
每台机器有P个输入输出规格。还有一个容量Q;
其中输入规格有三种情况:0,1,2
0:该部分不能存在
1:该部分必须保留
2:该部分可有可无
输出规格有2种情况:0,1
0:该部分不存在
1:该部分存在
要求的是生产电脑最大的台数,就是求网络中的最大流。
这相当于是生产线。需要自己去建图。
但是考虑到每台机器都有容量,所以把一台机器分成两个点,中间建一条容量的边。
同时如果一台机器的输出符合另一台机器的输入,则建一条容量无穷大的边。
同时要增加源点和汇点。输入没有1的连接源点,输出全部是1的连接汇点。
92 / 195 Problem B POJ 3281 Dining
本题能够想到用最大流做,那真的是太绝了。建模的方法很妙!
题意就是有N头牛,F个食物,D个饮料。
N头牛每头牛有一定的喜好,只喜欢几个食物和饮料。
每个食物和饮料只能给一头牛。一头牛只能得到一个食物和饮料。
而且一头牛必须同时获得一个食物和一个饮料才能满足。问至多有多少头牛可以获得满足。
最初相当的是二分匹配。但是明显不行,因为要分配两个东西,两个东西还要同时满足。
最大流建图是把食物和饮料放在两端。一头牛拆分成两个点,两点之间的容量为1.喜欢的食物和饮料跟牛建条边,容量为1.
加个源点和汇点。源点与食物、饮料和汇点的边容量都是1,表示每种食物和饮料只有一个。
这样话完全是最大流问题了,。
//1002 /* HDU 4289 G++ 62ms 1888K 最大流 SAP */ #include<stdio.h> #include<iostream> #include<map> #include<set> #include<algorithm> #include<string.h> #include<stdlib.h> using namespace std; const int MAXN=5000;//点数的最大值 const int MAXM=2500000;//边数的最大值 const int INF=0x3f3f3f3f; struct Node { int from,to,next; int cap; }edge[MAXM]; int tol; int head[MAXN]; int dep[MAXN]; int gap[MAXN];//gap[x]=y:说明残留网络中 dep[i]==x的个数为y int n;//点的实际个数,一定是总的点的个数,包括源点和汇点 void init() { tol=0; memset(head,-1,sizeof(head)); } void addedge(int u,int v,int w) { edge[tol].from=u; edge[tol].to=v; edge[tol].cap=w; edge[tol].next=head[u]; head[u]=tol++; edge[tol].from=v; edge[tol].to=u; edge[tol].cap=0; edge[tol].next=head[v]; head[v]=tol++; } void BFS(int start,int end) { memset(dep,-1,sizeof(dep)); memset(gap,0,sizeof(gap)); gap[0]=1; int que[MAXN]; int front,rear; front=rear=0; dep[end]=0; que[rear++]=end; while(front!=rear) { int u=que[front++]; if(front==MAXN)front=0; for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].to; if(edge[i].cap!=0||dep[v]!=-1)continue; que[rear++]=v; if(rear==MAXN)rear=0; dep[v]=dep[u]+1; ++gap[dep[v]]; } } } int SAP(int start,int end) { int res=0; BFS(start,end); int cur[MAXN]; int S[MAXN]; int top=0; memcpy(cur,head,sizeof(head)); int u=start; int i; while(dep[start]<n) { if(u==end) { int temp=INF; int inser; for(i=0;i<top;i++) if(temp>edge[S[i]].cap) { temp=edge[S[i]].cap; inser=i; } for(i=0;i<top;i++) { edge[S[i]].cap-=temp; edge[S[i]^1].cap+=temp; } res+=temp; top=inser; u=edge[S[top]].from; } if(u!=end&&gap[dep[u]-1]==0)//出现断层,无增广路 break; for(i=cur[u];i!=-1;i=edge[i].next) if(edge[i].cap!=0&&dep[u]==dep[edge[i].to]+1) break; if(i!=-1) { cur[u]=i; S[top++]=i; u=edge[i].to; } else { int min=n; for(i=head[u];i!=-1;i=edge[i].next) { if(edge[i].cap==0)continue; if(min>dep[edge[i].to]) { min=dep[edge[i].to]; cur[u]=i; } } --gap[dep[u]]; dep[u]=min+1; ++gap[dep[u]]; if(u!=start) u=edge[S[--top]].from; } } return res; } int main() { //freopen("B.in","r",stdin); //freopen("B.out","w",stdout); int N,M; int u,v; int start; int end; while(scanf("%d%d",&N,&M)!=EOF) { init(); scanf("%d%d",&start,&end); start=2*start-1; end=2*end; n=2*N; for(int i=1;i<=N;i++) { scanf("%d",&u); addedge(2*i-1,2*i,u); addedge(2*i,2*i-1,u); } while(M--) { scanf("%d%d",&u,&v); addedge(2*u,2*v-1,INF); addedge(2*v,2*u-1,INF);//这里一定要注意 } printf("%d\n",SAP(start,end)); } return 0; }
View Code
28 / 90 Problem J UVA 10480 Sabotage
最大流
19 / 37 Problem K HDU 2732 Leapin' Lizards
最大流
13 / 136 Problem L HDU 3338 Kakuro Extension
很神奇的最大流的题目。很有意思。
题目意思就是在n*m的格子中,有黑白两种格子。要在白格子中填入数字1~9
* 每一段横竖连续的白格子的和是知道的。
* 求出一种满足的,保证有解。
* 最大流。
* 按照横竖段进行编号。然后行进列出,构造图形。
*
* 为了保证填入的数字是1~9,所以一开始每个格子减掉了1,相应的流入和流出都减掉。
* 然后格子的边的赋值为8.
* 还有就是要记录下相应边的编号,便于输出结果。
36 / 358 Problem M HDU 3605 Escape
这题一看题目是很简单的最大流。
但是数据好大,试了很多模板,都是TLE。
后来发现可以合并点,
因为m<=10.
所以用二进制记录。
在n个点中,如果是一样的就合并。
这样最多是1024+m+2个点。
但是这题还是很坑。。。。在HDU上用G++交无论如何都是TLE的。直接读入数据输出都是TLE.
改成C++就AC了。。。
17 / 58 Problem N HDU 3081 Marriage Match II
最大流+二分+并查集
15 / 61 Problem O HDU 3416 Marriage Match IV
这题就是求从A到B的最短路径的条数。
一条边只能经过一次。
先通过最短路去除掉没有用的边。
然后用一次最大流就是答案了。
从A和B分别出发求最短路dist1,dist2.
注意从B求得额时候要反向。
如果dist1[a]+dist2[b]+c==dist1[B].那么这条边就是有用的。。
我用的SPFA求最短路的。
相关文章推荐
- HDU 4289 Control 网络流
- TCP 和 UDP 在socket编程中的区别
- 几个常见工具的使用
- Theano下用CNN(卷积神经网络)做车牌中文字符OCR
- Web中常见概念对比——URL&URI;HTML&XML;HTTP
- The type javax.servlet.http.HttpServletRequest cannot be resolved.
- 怎么判断大小端呢?
- 基于Http协议的Android网络编程
- 如何连接两个network namespace的网络
- HttpRequestMethodNotSupportedException
- HTTP Get请求URL最大长度
- nginx限制请求数(ngx_http_limit_req_module)模块
- 两种HTTP请求方法:GET和POST
- 网络
- SNA社交网络分析
- C++卷积神经网络实例(一)
- [一句秒懂]UILabel首行插入网络图片
- nginx限制连接数(ngx_http_limit_conn_module)模块
- Retrofit(重构——简单访问)
- 源泉书签,助您管理海量收藏。今日更新【里程碑】支持书签导出功能了,从此不怕网络书签丢失了,随时随地备份您的书签。