Max_Flow dinic

本文深入探讨了使用网络流算法解决资源分配问题的方法,并通过实例展示了算法优化的重要性。从理论到实践,详细介绍了如何利用算法解决实际问题。
BeiJing2006 狼抓兔子
#include<stdio.h>
#include<string.h>
#define MAXD 1000100
#define MAXM 6000600
#define INF 1000000000
int N, M, T, e, first[MAXD], next[MAXM], u[MAXM], v[MAXM], flow[MAXM];
int q[MAXD], d[MAXD], work[MAXD], s[MAXD];
void add(int a, int b, int f)
{
    u[e] = a;
    v[e] = b;
    flow[e] = f;
    next[e] = first[a];
    first[a] = e;
    e ++;
}
void init()
{
    int i, j, a, b, f;
    T = N * M - 1;
    e = 0;
    for(i = 0; i <= T; i ++)
        first[i] = -1;
    for(i = 0; i < N; i ++)
        for(j = 1; j < M; j ++)
        {
            scanf("%d", &f);
            a = i * M + j - 1;
            b = i * M + j;
            add(a, b, f);
            add(b, a, f);
        }
    for(i = 1; i < N; i ++)
        for(j = 0; j < M; j ++)
        {
            scanf("%d", &f);
            a = (i - 1) * M + j;
            b = i * M + j;
            add(a, b, f);
            add(b, a, f);
        }
    for(i = 1; i < N; i ++)
        for(j = 1; j < M; j ++)
        {
            scanf("%d", &f);
            a = (i - 1) * M + j - 1;
            b = i * M + j;
            add(a, b, f);
            add(b, a, f);
        }
}
int bfs()
{
    int i, j, rear;
    for(i = 1; i <= T; i ++)
        d[i] = -1;
    d[0] = 0;
    rear = 0;
    q[rear ++] = 0;
    for(i = 0; i < rear ; i ++)
        for(j = first[q[i]]; j != -1; j = next[j])
            if(flow[j] && d[v[j]] == -1)
            {
                d[v[j]] = d[q[i]] + 1;
                if(v[j] == T)
                    return 1;
                q[rear ++] = v[j];
            }
    return 0;
}
int dinic()
{
    int i, j, cur, r, res = 0;
    while(bfs())
    {
        r = 0;
        cur = 0;
        for(i = 0; i <= T; i ++)
            work[i] = first[i];
        for(;;)
        {
            if(cur == T)
            {
                int a = INF, minr = r;
                for(i = 0; i < r; i ++)
                    if(flow[s[i]] < a)
                    {
                        a = flow[s[i]];
                        minr = i;
                    }
                for(i = 0; i < r; i ++)
                {
                    flow[s[i]] -= a;
                    flow[s[i] ^ 1] += a;
                }
                r = minr;
                cur = u[s[r]];
                res += a;
            }
            for(i = work[cur]; i != -1; i = next[i])
                if(flow[i] && d[v[i]] == d[cur] + 1)
                    break;
            work[cur] = i;
            if(i != -1)
            {
                s[r ++] = i;
                cur = v[i];
            }
            else
            {
                d[cur] = -1;
                if(r == 0)
                    break;
                r --;
                cur = u[s[r]];
            }
        }
    }
    return res;
}
int main()
{
    while(scanf("%d%d", &N, &M) == 2)
    {
        init();
        int res = dinic();
        printf("%d\n", res);
    }
    return 0;
}

def partition_graph_by_key_nodes(transformed, key_nodes): """ 根据关键节点横向划分图 :param transformed: networkx图对象 :param key_nodes: 图的关键节点 :param source: 源点 :param sink: 汇点 :return: """ # 初始化子图列表 subgraphs = [] # 存储最大流,源点和汇点 final_max_flow = int(1e10) # 按关键节点分割图 for i in range(len(key_nodes) - 1): start_node = key_nodes[i] end_node = key_nodes[i + 1] # 获取从start_node开始的所有后继节点 successors = nx.descendants(transformed, start_node) successors.add(start_node) # 包括起始节点 # 获取从end_node开始的所有前驱节点 predecessors = nx.ancestors(transformed, end_node) predecessors.add(end_node) # 包括终止节点 # 交集部分即为分区节点 nodes_in_partition = successors & predecessors # 创建子图 subgraph = transformed.subgraph(nodes_in_partition).copy() ################################################################################################ # 计算子图的最大流,更新 #max_flow = nx.maximum_flow_value(subgraph, start_node, end_node) max_flow_, _ =max_flow(subgraph, start_node, end_node,ALGORITHM) ################################################################################################ if max_flow_value < final_max_flow: subgraphs.clear() final_max_flow = max_flow_value subgraphs.append((subgraph, start_node, end_node)) elif max_flow_value == final_max_flow: subgraphs.append((subgraph, start_node, end_node)) # draw_graph(subgraph, "images/subgraph_key_node_{}".format(i)) return subgraphs这样
09-15
def partition_graph_by_key_nodes(transformed, key_nodes): """ 根据关键节点横向划分图 :param transformed: networkx图对象 :param key_nodes: 图的关键节点 :param source: 源点 :param sink: 汇点 :return: """ # 初始化子图列表 subgraphs = [] # 存储最大流,源点和汇点 final_max_flow = int(1e10) # 按关键节点分割图 for i in range(len(key_nodes) - 1): start_node = key_nodes[i] end_node = key_nodes[i + 1] # 获取从start_node开始的所有后继节点 successors = nx.descendants(transformed, start_node) successors.add(start_node) # 包括起始节点 # 获取从end_node开始的所有前驱节点 predecessors = nx.ancestors(transformed, end_node) predecessors.add(end_node) # 包括终止节点 # 交集部分即为分区节点 nodes_in_partition = successors & predecessors # 创建子图 subgraph = transformed.subgraph(nodes_in_partition).copy() ################################################################################################ # 计算子图的最大流,更新 #max_flow = nx.maximum_flow_value(subgraph, start_node, end_node) max_flow_value, _ =max_flow(subgraph, start_node, end_node,ALGORITHM) ################################################################################################ if max_flow_value < final_max_flow: subgraphs.clear() final_max_flow = max_flow_value subgraphs.append((subgraph, start_node, end_node)) elif max_flow_value == final_max_flow: subgraphs.append((subgraph, start_node, end_node)) # draw_graph(subgraph, "images/subgraph_key_node_{}".format(i)) return subgraphs
09-15
def solve(file_path, t_type, t_num): start_time = time.time() #开始时间记录 # 读取路径 id_to_element, edges = read_paths(file_path) # 初始化图 graph = init_graph(id_to_element, edges) # 绘制原图 original_graph = nx.DiGraph() original_graph.add_nodes_from(graph["nodes"]) for u in graph["edges"]: for v in graph["edges"][u]: original_graph.add_edge(u, v, capacity=graph["nodes"][u]["capacity"]) draw_graph(original_graph, f"images/{t_type}/{t_num}/original_graph") # 转换图 transformed_graph, source, sink = transform_graph(graph, id_to_element) draw_graph(transformed_graph, f"images/{t_type}/{t_num}/transformed_graph") transformed_node_count = transformed_graph.number_of_nodes() transformed_edge_count = transformed_graph.number_of_edges() # 计算最大流 max_flow_value1, flow_dict1 = max_flow(transformed_graph, source, sink,ALGORITHM) time1 = time.time() # origion_min_cuts = all_min_cuts(transformed_graph, max_flow_value1, flow_dict1, source, sink) origion_min_cuts = [] time2 = time.time() print("最小割容量:", max_flow_value1) print(f"共有{len(origion_min_cuts)}个割集") # 重点收缩 time3 = time.time() transformed_graph, source, sink = contract_graph_node(transformed_graph, max_flow_value1, is_heavy_node) time4 = time.time() draw_graph(transformed_graph, f"images/{t_type}/{t_num}/heavy_node_graph") heavy_node_count = transformed_graph.number_of_nodes() heavy_edge_count = transformed_graph.number_of_edges() ######################################################################################################## # 计算最大流 max_flow_value2, flow_dict2 = max_flow(transformed_graph, source, sink,ALGORITHM) print(f"重点收缩后的最大流与原始最大流的差值:{max_flow_value2 - max_flow_value1}") ######################################################################################################## # 度为1的节点收缩 time5 = time.time() transformed_graph, source, sink = contract_graph_node(transformed_graph, max_flow_value2, is_one_degree_node) time6 = time.time() draw_graph(transformed_graph, f"images/{t_type}/{t_num}/one_degree_node_graph") one_degree_node_count = transformed_graph.number_of_nodes() one_degree_edge_count = transformed_graph.number_of_edges() ######################################################################################################## # 计算最大流 max_flow_value3, flow_dict3 = max_flow(transformed_graph, source, sink,ALGORITHM) print(f"度为1的节点收缩后的最大流与重点收缩后的最大流的差值:{max_flow_value3 - max_flow_value2}") ############################################################################################################################################ # 求解所有最小割 time7 = time.time() third_min_cuts = all_min_cuts(transformed_graph, max_flow_value3, flow_dict3, source, sink) time8 = time.time() ############################################################################################################################################# # 记录时间 print(f"收缩后的时间消耗:{time8 - time7}") # 识别关键节点 time9 = time.time() key_nodes = identify_critical_nodes(transformed_graph, source, sink) time10 = time.time() all_cuts, all_number, max_flow_final = process_subgraph(transformed_graph, source, sink) # 按照关键节点划分子图 # subgraphs = partition_graph_by_key_nodes(transformed_graph, key_nodes) # all_cuts = [] # all_number = 0 # max_flow_final = 0 # for idx, (subgraph, sub_source, sub_sink) in enumerate(subgraphs): # subgraph_list = partition_graph(subgraph, sub_source, sub_sink) # sub_cuts = [] # max_flow_value_all = 0 # sub_all_number = 1 # for sub_idx, sub in enumerate(subgraph_list): # max_flow_value, flow_dict = max_flow(sub, sub_source, sub_sink) # max_flow_value_all += max_flow_value # min_cuts = all_min_cuts(sub, max_flow_value, flow_dict, sub_source, sub_sink) # sub_all_number *= len(min_cuts) # sub_cuts.append(min_cuts) # all_cuts.append(sub_cuts) # all_number += sub_all_number # max_flow_final = max(max_flow_final, max_flow_value_all) time11 = time.time() print(all_cuts) print(f"采用切割后的时间消耗:{time11 - time10}") print(f"图中最小割的数量:{all_number}") print(f"最大流的值:{max_flow_final}") # 记录时间消耗 heavy_node_contraction_time = round(time4 - time3, 3) one_degree_node_contraction_time = round(time6 - time5, 3) identify_critical_nodes_time = round(time10 - time9, 3) origion_min_cuts_time = round(time2 - time1, 3) subgraph_cut_time = round(time11 - time10, 3) shrink_cut_time = round(time8 - time7, 3) end_time = time.time() #结束时间记录 total_time = round(end_time - start_time, 3) #总运行时间 return ( transformed_node_count, transformed_edge_count, heavy_node_count, heavy_edge_count, one_degree_node_count, one_degree_edge_count, heavy_node_contraction_time, one_degree_node_contraction_time, identify_critical_nodes_time, origion_min_cuts_time, subgraph_cut_time, len(origion_min_cuts), shrink_cut_time, all_number, max_flow_value1, max_flow_final,total_time )是这样吗
09-15
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值