线性规划与网络流24题の1 飞行员配对方案问题(最大匹配)
来源:互联网 发布:鳄鱼毒品知乎 编辑:程序博客网 时间:2024/05/01 13:52
最大流水题。就二分图最大匹配数。
输出方案不唯一...=。=,所以在没有special judge的OJ会出错(也是实在没想明白标程的解是怎么输出的。。。
//#pragma comment(linker,"/STACK:1024000000,1024000000")#include <map>#include <set>#include <cmath>#include <queue>#include <stack>#include <cstdio>#include <string>#include <vector>#include <cstring>#include <iostream>#include <algorithm>using namespace std;typedef double DB;typedef long long ll;typedef pair<int, int> PII;#define pb push_back#define MP make_pair#define lson l, m, rt << 1#define rson m + 1, r, rt << 1 | 1const DB eps = 1e-6;const int inf = ~0U>>1;const ll INF = 0x3f3f3f3f3f3f3f3f;const int mod = 1000000007;const int maxn = 40000 + 10;///init是初始化要在加边之前初始化,然后调用max_flow(顶点数,边数,源点, 汇点)const int maxv = 40000 + 10;///顶点个数const int maxe = 1000000 + 10;///边数int c[maxe];struct node{ int v, cap, next;}edge[maxe];int head[maxv], cnt;int n;///n是节点个数,m是边数int st, ed;///st是源点,ed是汇点int gap[maxv], h[maxv];void addedge(int u, int v, ll w){///有向图加边 edge[cnt].v = v; edge[cnt].cap = w; edge[cnt].next = head[u]; head[u] = cnt++;///正向边 edge[cnt].v = u; edge[cnt].cap = 0; edge[cnt].next = head[v]; head[v] = cnt++;///反向边}int dfs(int x, int cost){ if(x == ed) return cost; ///当前节点是汇点,直接返回cost int can = cost, d, minh = n - 1; for(int i=head[x]; ~i; i=edge[i].next){ int v = edge[i].v, w = edge[i].cap; if(w > 0){///如果这条边的容量大于0 if(h[v] + 1 == h[x]){///如果这是允许弧 if(can > w) d = w;///如果当前弧的容量小于之前可增广的容量 else d = can; d = dfs(v, d);///从v开始可增广的容量为d ///更新弧的容量和可增广的容量 edge[i].cap -= d; edge[i ^ 1].cap += d; can -= d; if(h[st] >= n) return cost - can; if(!can) break;///不能再继续增广 } if(h[v] < minh) minh = h[v];///更新最小标号 } } if(can == cost){///如果没有增广...GAP gap[h[x]]--; if(gap[h[x]] == 0) h[st] = n;///存在断层,没有增广路了 h[x] = minh + 1;///重新标记,保证下次再访问的时候有流量 gap[h[x]]++; } return cost - can;///在这个点之前可以增广的 - 访问这个点之后可以增广的 = 在这个点增广的容量}int max_flow(int N){///SAP+GAP优化 n = N;//m = M; for(int i=0; i<cnt; i++) c[i] = edge[i].cap; memset(h, 0, sizeof(h));///h[i]表示i节点的标号 memset(gap, 0, sizeof(gap));///gap[i]表示标号为i的节点个数 gap[0] = n;///初始有n个节点标号为0 int ret = 0; while(h[st] < n){ ret += dfs(st, inf); } return ret;}void init(int source, int sink){ memset(head, -1, sizeof(head)); cnt = 0; st = source; ed = sink;}///求割集bool vis[maxn];void Dfs(int x){ vis[x] = true; for(int i=head[x]; ~i; i=edge[i].next){ if(edge[i].cap > 0 && !vis[edge[i].v]) Dfs(edge[i].v); }}int N, M;int main(){ cin >> M >> N; init(0, N + 1); for(int i=1; i<=M; i++) addedge(st, i, 1); for(int i=M+1; i<=N; i++) addedge(i, ed, 1); int u, v; while(scanf("%d%d", &u, &v) == 2){ if(u == -1 && v == -1) break; addedge(u, v, 1); } int ans = max_flow(N + 2); if(ans == 0) {puts("No Solution!"); return 0;} cout << ans << endl; for(int i=head[st]; ~i; i=edge[i].next) if(edge[i].cap == 0){ int u = edge[i].v; for(int j=head[u]; ~j; j=edge[j].next) if(edge[j].v != st && edge[j].cap == 0){ printf("%d %d\n", u, edge[j].v); break; } } return 0;}
0 0
- 线性规划与网络流24题の1 飞行员配对方案问题(最大匹配)
- 线性规划与网络流24题 飞行员配对方案问题
- P3386 【模板】二分图匹配(网络流与线性规划24题01飞行员配对方案问题)
- 【线性规划与网络流24题 1】飞行员配对方案
- 【线性规划与网络流24题 1】飞行员配对方案
- 线性规划与网络流24题 1飞行员配对方案问题
- 线性规划与网络流24题之飞行员配对计划 二分图的最大匹配
- 线性规划与网络流24题 01飞行员配对方案问题
- 线性规划与网络流24题——01飞行员配对方案问题
- 网络流与线性规划24题01飞行员配对方案问题
- 网络流与线性规划24题01飞行员配对方案问题
- 线性规划与网络流24题 1.飞行员配对方案问题(nefu 475)
- 网络流与线性规划24题01飞行员配对方案问题
- 【线性规划与网络流】飞行员配对方案问题
- [网络流24题] 飞行员配对方案问题 最大流 二分图最大匹配
- 线性规划与网络流24——飞行员配对方案问题
- 网络流24题 01 飞行员配对方案问题 (多源多汇点+最大流)
- [网络流24题 #1]飞行员配对方案问题
- JspWriter与PrintWriter(转)
- 【1138】数据结构上机测试2-1:单链表操作A(顺序建表+删除节点)(SDUT)
- CF 461B Appleman and Tree (树形dp)
- Android调用so文件(C代码库)方法详解
- 下拉刷新控件SwipeRefreshLayout用法简介
- 线性规划与网络流24题の1 飞行员配对方案问题(最大匹配)
- dumpsys SurfaceFlinger
- hdu 1874 畅通工程续
- 斐波那契序列程序优化
- PCB设计资料:看到最后才知道是福利
- 老城里斯本简介
- HDU 3255 Farming(线段树求体积并)
- 解决Firefox 27中AutoProxy不能订阅代理规则的方法
- 番外:菜鸟如何读优秀 JS 开源项目之“2048”