网络流之最大流板子题

在做最大流的题目之前,需要知道两个算法:EK与DINIC,但是鉴于我没有过多时间(特别懒),不想写基础知识与算法的推导,所以在此推荐两篇blog:(传送门1传送门2

板子题1:

  poj1273lougu2740codevs1993.此题很明显,一入眼就知道这是一个纯正的最大流板子题,没什么好写的,注意的是,poj中的题目是有多组数据的,然而题目中却没有写,让我一脸懵逼的WA了好几次(我好菜我好菜),洛谷和codevs则没有这个问题。不废话了,上代码!!
这是EK算法的:

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<algorithm>
 6 #include<cstdlib>
 7 #include<queue>
 8 using namespace std;
 9 int n,m,g[1005][1005],pre[2005],flow[2005];
10 queue <int> q;
11 int bfs(int s,int t)
12 {
13     while (!q.empty()) q.pop();
14     for (int i=1; i<=n; i++) pre[i]=-1;
15     pre[s]=0; q.push(s); flow[s]=20252025;
16     while (!q.empty()){
17         int x=q.front(); q.pop();
18         if (x==t) break;
19         for (int i=1; i<=n; i++)
20             if (g[x][i]>0 && pre[i]==-1){
21                 pre[i]=x;
22                 flow[i]=min(flow[x],g[x][i]);
23                 q.push(i);
24             }
25     }
26     if (pre[t]==-1) return -1;
27     else return flow[t];
28 }
29 int EK(int s,int t)
30 {
31     int increase=0,maxflow=0;
32     while ((increase=bfs(s,t))!=-1){
33         int k=t;
34         while (k!=s){
35             int xx=pre[k];
36             g[xx][k]-=increase;
37             g[k][xx]+=increase;
38             k=xx;
39         }
40         maxflow+=increase;
41     }
42     return maxflow;
43 }
44 int main()
45 {
46     while (~scanf("%d%d",&m,&n)){
47         memset(g,0,sizeof(g)); memset(flow,0,sizeof(flow));
48         for (int i=1; i<=m; i++){
49             int x,y,v;
50             scanf("%d%d%d",&x,&y,&v);
51             g[x][y]+=v;
52         }
53         int ans=EK(1,n);
54         cout<<ans<<endl;
55     }
56     return 0;
57 }

 

这是DINIC算法的:(未加多组数据)

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<algorithm>
 6 #include<cstdlib>
 7 #include<queue>
 8 using namespace std;
 9 queue<int> q;
10 int n,m,x,y,z,maxflow,deep[505],vet[505],next[505],head[505],cur[505],dis[505],edgenum=-1;
11 const int INF=1e9;
12 void addedge(int u,int v,int t)
13 {
14     vet[++edgenum]=v;
15     next[edgenum]=head[u];
16     head[u]=edgenum;
17     dis[edgenum]=t;
18 }
19 bool bfs(int s,int t)
20 {
21     memset(deep,0x7f,sizeof(deep));
22     while (!q.empty()) q.pop();
23     for (int i=1; i<=n; i++) cur[i]=head[i];
24     deep[s]=0; q.push(s);
25     while (!q.empty()){
26         int x=q.front(); q.pop();
27         for (int e=head[x]; e!=-1; e=next[e])
28             if (deep[vet[e]]>INF && dis[e]){
29                 deep[vet[e]]=deep[x]+1;
30                 q.push(vet[e]);
31             }
32     }
33     if (deep[t]<INF) return true; else return false;
34 }
35 int dfs(int now,int t,int limit)
36 {
37     if (!limit || now==t) return limit;
38     int flow=0,f;
39     for (int e=cur[now]; e!=-1; e=next[e]){
40         cur[now]=e;
41         if ((deep[vet[e]]==(deep[now]+1)) && (f=dfs(vet[e],t,min(limit,dis[e])))){
42             flow+=f; limit-=f;
43             dis[e]-=f;
44             dis[e^1]+=f;
45             if (!limit) break;
46         }
47     }
48     return flow;
49 }
50 void dinic(int s,int t)
51 {
52     while (bfs(s,t)) maxflow+=dfs(s,t,INF);
53 }
54 int main()
55 {
56     scanf("%d%d",&m,&n);
57     memset(head,-1,sizeof(head));
58     for (int i=1; i<=m; i++){
59         int x,y,v;
60         scanf("%d%d%d",&x,&y,&v);
61         addedge(x,y,v); addedge(y,x,0);
62     }
63     dinic(1,n);
64     cout<<maxflow<<endl;
65     return 0;
66 }

板子题2:

  poj1459.这一道题目看一眼题面,稍加思考便可知此为最大流算法,我们只需要建立一个超级源点与超级汇点,将超级源点与发电站相连,超级汇点与用电处相连,跑一遍dinic便可。

 

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<algorithm>
 6 #include<cstdlib>
 7 #include<queue>
 8 using namespace std;
 9 queue<int> q;
10 const int INF=1e9;
11 int vet[30005],next[30005],head[30005],dis[300005],cur[30005],edgenum=-1,n,np,nc,m,deep[30005],maxflow,sp,fp;
12 void addedge(int u,int v,int t)
13 {
14     vet[++edgenum]=v;
15     next[edgenum]=head[u];
16     head[u]=edgenum;
17     dis[edgenum]=t;
18 }
19 bool bfs(int s,int t)
20 {
21     for (int i=1; i<=n; i++) cur[i]=head[i];
22     memset(deep,0x7f,sizeof(deep)); deep[s]=0;
23     while (!q.empty()) q.pop(); q.push(s);
24     while (!q.empty()){
25         int x=q.front(); q.pop();
26         for (int e=head[x]; e!=-1; e=next[e])
27             if (deep[vet[e]]>INF && dis[e]){
28                 deep[vet[e]]=deep[x]+1;
29                 q.push(vet[e]);
30             }
31     }
32     if (deep[t]>INF) return false; else return true;
33 }
34 int dfs(int now,int t,int limit)
35 {
36     int flow=0,f;
37     if (!limit || now==t) return limit;
38     for (int e=cur[now]; e!=-1; e=next[e]){    
39         cur[now]=e;
40         if ((deep[vet[e]]==deep[now]+1) && (f=dfs(vet[e],t,min(limit,dis[e])))){
41             dis[e]-=f; limit-=f;
42             flow+=f; dis[e^1]+=f;
43             if (!limit) break;
44         }
45     }
46     return flow;
47 }
48 void dinic(int s,int t)
49 {
50     while (bfs(s,t)) maxflow+=dfs(s,t,INF);
51 }
52 int main()
53 {
54     while (~scanf("%d%d%d%d",&n,&np,&nc,&m)){
55         memset(head,-1,sizeof(head)); memset(next,-1,sizeof(next)); memset(dis,0,sizeof(dis)); edgenum=-1;
56         memset(cur,0,sizeof(cur)); char ch; maxflow=0;
57         for (int i=1; i<=m; i++){
58             int x,y,z;
59             cin>>ch>>x>>ch>>y>>ch>>z; x++; y++;
60             addedge(x,y,z); addedge(y,x,0);
61         }
62         sp=n+1; fp=n+2; n+=2;
63         for (int i=1; i<=np; i++){
64             int x,y;
65             cin>>ch>>x>>ch>>y; x++;
66             addedge(sp,x,y); addedge(x,sp,0);
67         }
68         for (int i=1; i<=nc; i++){
69             int x,y;
70             cin>>ch>>x>>ch>>y; x++;
71             addedge(x,fp,y); addedge(fp,x,0);
72         }
73         dinic(sp,fp);
74         cout<<maxflow<<endl;
75     }
76     return 0;
77 }

 

转载于:https://www.cnblogs.com/wangyh1008/p/9355098.html

引用\[1\]:Dijkstra算法是一种用于解决单源最短路径问的算法。它通过不断更新起始点到其他点的最短距离来找到最短路径。\[1\]引用\[2\]:在稀疏图中,节点数较多时,朴素的Dijkstra算法可能会超时。为了解决这个问,堆优化版的Dijkstra算法应运而生。\[2\]引用\[3\]:Dijkstra算法的实现通常使用邻接链表来存储边和权值。算法的核心思想是通过优先队列来选择当前距离起始点最近的节点,并更新其后继节点的最短距离。\[3\] 问: Dijkstra算法是用来解决什么问的?它的实现原理是什么? 回答: Dijkstra算法是用来解决单源最短路径问的算法,即找到起始点到其他点的最短路径。它的实现原理是通过不断更新起始点到其他点的最短距离来找到最短路径。在稀疏图中,节点数较多时,可以使用堆优化版的Dijkstra算法来提高效率。该算法使用邻接链表来存储边和权值,并通过优先队列来选择当前距离起始点最近的节点,并更新其后继节点的最短距离。 #### 引用[.reference_title] - *1* *2* *3* [Dijkstra学习笔记(模板+acwing上的)](https://blog.csdn.net/weixin_51368613/article/details/123114128)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值