ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

P1231 教辅的组成

2021-05-29 18:51:40  阅读:119  来源: 互联网

标签:now ch int flow 教辅 P1231 ans include 组成


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

 

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

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

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

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

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<algorithm>
  4 #include<cmath>
  5 #include<cstring>
  6 #include<cstdlib>
  7 #include<cctype>
  8 #include<stack>
  9 #include<queue>
 10 #include<vector>
 11 using namespace std;
 12 #define enter printf("\n")
 13 #define space printf(" ")
 14 #define Mem(a) memset(a, 0, sizeof(a))
 15 typedef long long ll;
 16 typedef double db;
 17 const int INF = 0x3f3f3f3f;
 18 const db eps = 1e-8;
 19 const int maxn = 1e4 + 5;
 20 inline ll read()
 21 {
 22     ll ans = 0;
 23     char ch = getchar(), last = ' ';
 24     while(!isdigit(ch)) {last = ch; ch = getchar();}
 25     while(isdigit(ch))
 26     {
 27         ans = ans * 10 + ch - '0'; ch = getchar();
 28     }
 29     if(last == '-') ans = -ans;
 30     return ans;
 31 }
 32 inline void write(ll x)
 33 {
 34     if(x < 0) x = -x, putchar('-');
 35     if(x >= 10) write(x / 10);
 36     putchar(x % 10 + '0');
 37 }
 38 
 39 int t, n1, n2, n3;
 40 
 41 struct Edge
 42 {
 43     int from, to, cap, flow;
 44 };
 45 vector<Edge> edges;
 46 vector<int> G[maxn << 2];
 47 void addEdge(int from, int to)
 48 {
 49     edges.push_back((Edge){from, to, 1, 0});
 50     edges.push_back((Edge){to, from, 0, 0});
 51     int sz = edges.size();
 52     G[from].push_back(sz - 2);
 53     G[to].push_back(sz - 1);
 54 }
 55 
 56 int dis[maxn << 2];
 57 bool vis[maxn << 2];
 58 bool bfs()
 59 {
 60     Mem(vis);
 61     queue<int> q;
 62     q.push(0); vis[0] = 1;
 63     dis[0] = 0;
 64     while(!q.empty())
 65     {
 66         int now = q.front(); q.pop();
 67         for(int i = 0; i < (int)G[now].size(); ++i)
 68         {
 69             Edge& e = edges[G[now][i]];
 70             if(!vis[e.to] && e.cap > e.flow)
 71             {
 72                 vis[e.to] = 1;
 73                 dis[e.to] = dis[now] + 1;
 74                 q.push(e.to);
 75             }
 76         }
 77     }
 78     return vis[t];
 79 }
 80 int cur[maxn << 2];
 81 int dfs(int now, int a)
 82 {
 83     if(now == t || !a) return a;
 84     int flow = 0, f;
 85     for(int& i = cur[now]; i < (int)G[now].size(); ++i)
 86     {
 87         Edge& e = edges[G[now][i]];
 88         if(dis[e.to] == dis[now] + 1 && (f = dfs(e.to, min(a, e.cap - e.flow))) > 0)
 89         {
 90             e.flow += f;
 91             edges[G[now][i] ^ 1].flow -= f;        
 92             flow += f; a -= f;
 93             if(!a) break;    
 94         }
 95     }
 96     return flow;
 97 }
 98 
 99 int maxflow()
100 {
101     int flow = 0;
102     while(bfs())
103     {
104         Mem(cur);
105         flow += dfs(0, INF);
106     }
107     return flow;
108 }
109 
110 //bool vis2[maxn];
111 
112 int main()
113 {
114     n1 = read(); n2 = read(); n3 = read();         
115     t = (n1 << 1)+ n2 + n3 + 1;                //为了防止编号重复
116 /*按注释掉的写法会WA掉,因为如果一本书多次输入,那么这个书
117 就多次拆点,这一本书就可以使用多次了 */ 
118 /*    int m = read();                            
119     while(m--)
120     {
121         int x = read(), y = read();        
122         addEdge(0, y + (n1 << 1));
123         addEdge(y + (n1 << 1), x);
124         addEdge(x, x + n1);
125         vis2[x] = 1;
126     }
127     m = read();
128     while(m--)
129     {
130         int x = read(), y = read();
131         if(!vis2[x]) addEdge(x, x + n1), vis2[x] = 1;
132         addEdge(x + n1, y + (n1 << 1) + n2);
133         addEdge(y + (n1 << 1) + n2, t);
134     }*/
135     int m = read();
136     while(m--)
137     {
138         int x = read(), y = read();
139         addEdge(y + (n1 << 1), x);
140     }
141     m = read();
142     while(m--)
143     {
144         int x = read(), y = read();
145         addEdge(x + n1, y + (n1 << 1) + n2);
146     }
147     for(int i = 1; i <= n1; ++i) addEdge(i, i + n1);
148     for(int i = 1; i <= n2; ++i) addEdge(0, i + (n1 << 1));
149     for(int i = 1; i <= n3; ++i) addEdge(i + (n1 << 1) + n2, t);
150     write(maxflow()); enter;
151 }

 

标签:now,ch,int,flow,教辅,P1231,ans,include,组成
来源: https://blog.51cto.com/u_15234622/2830855

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有