max_flow(Dinic)

本文探讨了在图论中应用流量网络优化算法的实现方式,具体包括使用广度优先搜索(BFS)和深度优先搜索(DFS)算法进行最大流问题求解。通过实例展示了算法的应用步骤,并提供了代码实现细节。
    #include <cstdio>
    #include <iostream>
    #include <cstring>
    #include<queue>
    #include<cmath>

    using namespace std;
    const int INF = 0x3fffffff;

    int  g[1005][1005];
    int pre[1005];

    int m;

    int bfs(int s,int t)
    {

        queue<int>q;
        q.push(s);
        memset(pre,0,sizeof(pre));
        pre[s] = 1;
        while(q.size())
        {

            int v = q.front();
            q.pop();
            for(int i=1;i<=m;i++)
            {
                if(pre[i]==0 && g[v][i]>0)
                {
                    pre[i] = pre[v] + 1;
                    q.push(i);
                }
            }
        }
        if(pre[t]==0)   return 0;
        return 1;
    }

    int dfs(int s,int t,int f)
    {
        if(s==t)    return f;
        for(int i=1;i<=m;i++)
        {
            if(g[s][i] && pre[i]==pre[s]+1)
            {
                int d = dfs(i,t,min(f,g[s][i]));
                if(d>0)
                {
                    g[s][i]-=d;
                    g[i][s]+=d;
                    return d;
                }
            }
        }
        return 0;
    }

    int find_flows(int s,int t)
    {
        int f = 0;
        while(bfs(s,t))
        {
            f += dfs(s,t,INF);
        }
        return f;
    }

    int main()
    {
        int a, b, len;
        int s, t, p;
            scanf("%d%d", &m, &p);
            scanf("%d%d",&s,&t);
            memset(g,0,sizeof(g));

            while(p--)
            {
                scanf("%d%d%d", &a, &b, &len);
                g[a][b] += len;
            }
            printf("%d\n", find_flows(s,t));
        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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值