P3376 【模板】网络最大流 当前弧优化

本文深入探讨了Dinic算法的原理与应用,这是一种高效的网络流算法,用于解决最大流问题。通过详细的代码解析,展示了如何在C++中实现Dinic算法,并提供了完整的示例代码。适用于对网络流算法感兴趣的读者。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include<bits/stdc++.h>?
#include<iostream>
#include<cstring>
#include<stack>
#include<stdio.h>
const int maxn = 1e4 + 10;
int head[maxn];
int dft[maxn];
int cur[maxn];
int tot;
int n, m, S, T;
using namespace std;
struct node{
    int to;
    int next;
    int w;
    node() {}
    node(int a, int b, int c) : to(a), next(b), w(c) {}
}edge[maxn * 2];
 
void edgeadd(int a, int b, int c){
    edge[tot] = node(b, head[a], c);
    head[a] = tot++;
    edge[tot] = node(a, head[b], 0);
    head[b] = tot++;
}
 
int bfs(int s, int e){
    memset(dft, 0, sizeof(dft));
    queue<int> q;
    q.push(s);
    dft[s] = 1;
    while(!q.empty()){
        int nw = q.front();
        q.pop();
        for(int i = head[nw]; i != -1; i = edge[i].next){
            int w = edge[i].w;
            int v = edge[i].to;
            if(w <= 0 || dft[v]) continue;
            dft[v] = dft[nw] + 1;
            q.push(v);
        }
    }
    return dft[e]; 
} 
 
int dfs(int s, int e, int f){
    if(s == e) return f;
    int ans = 0;
    for(int i = cur[s]; i != -1; i = edge[i].next){
        int v = edge[i].to;
        int w = edge[i].w;
        cur[s] = i;
        if(dft[v] != dft[s] + 1 || w <= 0)
            continue;
        int we = dfs(v, e, min(w, f - ans));//由于多次增广, 不能为f
        edge[i].w -= we;
        edge[i ^ 1].w += we;
        ans += we;
    }
    return ans;
}
void init(){
    memset(head, -1, sizeof(head));
    tot = 0;
}
 
int dinic(int s, int e){
    int cnt = 0;
    while(bfs(s, e)){
        for(int i = 1; i <= n; i++){
            cur[i] = head[i];
        } 
        cnt += dfs(s, e, 0x3f3f3f3f);
    }
    return cnt;
}
 
int main(){
    ios::sync_with_stdio(false);
    cin >> n >> m >> S >> T;
    init();
    for(int i = 1; i <= m; i++){
        int a, b, c;
        cin >> a >> b >> c;
        edgeadd(a, b , c);
    }
    cout << dinic(S, T) << endl;
    return 0;
}

 

折痕扩展角度有问题,改,完整代码% main_multiple_folds.m - 多折痕曲纹折纸机构运动学建模 % Multi-fold curved origami mechanism kinematic modeling clear; clc; close all %% 参数设置 - Parameter Settings % 思路:基于单个折痕的扩展逻辑,将折痕横向扩展到多条 % Concept: Extend single fold logic to multiple parallel folds % 生成扇形角度 - Generate sector angles theta_deg = []; N_vertices = 40; % 每条折痕的顶点数 - Number of vertices per fold N_folds = 3; % 折痕数量 - Number of folds % 为每个顶点生成扇形角度 - Generate sector angles for each vertex theta_deg(:,1) = 90.2*ones(N_vertices,1) + rand(N_vertices,1)*0; theta_deg(:,2) = 89.9*ones(N_vertices,1) + rand(N_vertices,1)*0; % theta_deg(:,3) = 89.9*ones(N_vertices,1) + rand(N_vertices,1)*0; theta_deg(:,3) = 180*ones(N_vertices,1) - theta_deg(:,1); % 川崎定理 theta_deg(:,4) = 360*ones(N_vertices,1) - (theta_deg(:,1)+theta_deg(:,2)+theta_deg(:,3)); %% 主循环参数 - Main loop parameters for i_total =0 % 折叠角度参数 - Folding angle parameter % 基本参数设置 - Basic parameter setup l_initial = [1,0.5, 1]*0.1; % 初始长度 - Initial lengths c_scale = 1.02; % 缩放因子 - Scaling factor rho_initial_deg = i_total; % 初始折叠角度 - Initial folding angle sigma_mv = 1; % 山谷折叠分配 - Mountain-Valley assignment sigma_geom_choice = -1; % 几何选择参数 - Geometry choice parameter % 转换为度 - Convert to radians theta_rad = deg2rad(theta_deg); rho_central_rad = deg2rad(i_total); %% 计算初始折痕 - Calculate initial fold [P_center_0, P_left_0, P_right_0, actual_N_vertices] = calculate_3d_strip_geometry(... theta_rad, rho_central_rad, l_initial, c_scale, sigma_geom_choice, N_vertices); if isempty(P_center_0) fprintf('Failed to calculate initial 3D geometry. Check parameters.\n'); return; end %% 多折痕扩展 - Multiple fold expansion % 存储所有折痕的数据 - Store data for all folds P_center_all = cell(N_folds, 1); % 中心线点 - Center line points P_left_all = cell(N_folds, 1); % 左边界点 - Left boundary points P_right_all = cell(N_folds, 1); % 右边界点 - Right boundary points % 第一条折痕(原始折痕)- First fold (original fold) P_center_all{1} = P_center_0; P_left_all{1} = P_left_0; P_right_all{1} = P_right_0; % 生成多条折痕 - Generate multiple folds for fold_idx = 2:N_folds % 获取前一条折痕作为参考 - Get previous fold as reference PR_prev_center = P_right_all{fold_idx-1}; PR_prev_left = P_center_all{fold_idx-1}; %% 计算前一条折痕的角度参数 - Calculate angle parameters for previous fold PR_th2_ = zeros(1, length(PR_prev_center)-1); PR_th3_ = zeros(1, length(PR_prev_center)-1); for i_ = 1:length(PR_prev_center)-1 % 计算向量夹角 - Calculate vector angles A = (PR_prev_center(:,i_+1) - PR_prev_center(:,i_)); B = (PR_prev_left(:,i_) - PR_prev_center(:,i_)); dot_product = dot(A, B); norm_A = norm(A); norm_B = norm(B); cos_theta = dot_product / (norm_A * norm_B); B1 = (PR_prev_left(:,i_+1) - PR_prev_center(:,i_+1)); dot_product1 = dot(-A, B1); norm_B1 = norm(B1); cos_theta1 = dot_product1 / (norm_A * norm_B1); if i_ == 1 PR_th2_(i_) = acos(cos_theta); PR_th3_(i_) = 0; else PR_th2_(i_) = acos(cos_theta); PR_th3_(i_) = acos(cos_theta1); end end %% 计算新折痕的角度参数 - Calculate new fold angle parameters PR_th2 = rad2deg(PR_th2_(end)); PR_th3 = rad2deg(PR_th3_(end)); PR_th0 = 91; PR_th1 = 360 - PR_th2 - PR_th3 - PR_th0; %% 生成新折痕的右边界 - Generate right boundary for new fold % 计算第一个点的位置 - Calculate position of first point A = (PR_prev_center(:,2) - PR_prev_center(:,1)); B = (PR_prev_left(:,1) - PR_prev_center(:,1)); % 计算法向量 - Calculate normal vector PR_normal_Vector = cross(A, B); if rem(fold_idx,2)==1 sign_flag = -1; else sign_flag = 1; end % 旋转法向量 - Rotate normal vector PR_right_normal_Vector = (RotationofRandL(PR_prev_center(:,1), ... PR_prev_center(:,1) + PR_normal_Vector, A, deg2rad(sign_flag*i_total))) - PR_prev_center(:,1)'; % 计算旋转后的点 - Calculate rotated point PR_right_ = RotationofRandL(PR_prev_center(:,1), PR_prev_center(:,2), ... PR_right_normal_Vector/norm(PR_right_normal_Vector), -deg2rad(PR_th1)); % 新折痕的右边界点 - Right boundary points for new fold PR_right = zeros(3, N_vertices); PR_right(:,1) = PR_prev_center(:,1) + l_initial(3) * ... (PR_right_' - PR_prev_center(:,1)) / norm((PR_right_' - PR_prev_center(:,1))); % 迭代计算其余点 - Iteratively calculate remaining points for i = 2:N_vertices A = (PR_right(:,i-1) - PR_prev_center(:,i-1)); B = (PR_prev_center(:,i) - PR_prev_center(:,i-1)); PR_normal_Vector = cross(A, B); PR_right_normal_Vector = PR_normal_Vector / norm(PR_normal_Vector); PR_right_1 = RotationofRandL(PR_prev_center(:,i), PR_prev_center(:,i-1), ... PR_right_normal_Vector / norm(PR_right_normal_Vector), deg2rad(PR_th0)); PR_right(:,i) = PR_prev_center(:,i) + l_initial(3) * c_scale^i * ... (PR_right_1' - PR_prev_center(:,i)) / norm((PR_right_1' - PR_prev_center(:,i))); end % 存储新折痕数据 - Store new fold data P_center_all{fold_idx} = PR_prev_center; P_left_all{fold_idx} = PR_prev_left; P_right_all{fold_idx} = PR_right; % 打印进度信息 - Print progress information fprintf('第 %d 条折痕计算完成 - Fold %d calculation completed\n', fold_idx, fold_idx); end %% 可视化所有折痕 - Visualize all folds figure(122); clf; % 清除图形 - Clear figure hold on; axis equal; % 颜色映射 - Color mapping colors = jet(N_folds); for fold_idx = 1:N_folds P_center_curr = P_center_all{fold_idx}; P_left_curr = P_left_all{fold_idx}; P_right_curr = P_right_all{fold_idx}; % 绘制每个折痕的面板 - Draw panels for each fold for i = 1:N_vertices-1 % 左面板坐标 - Left panel coordinates x_l = [P_center_curr(1,i) P_center_curr(1,i+1) P_left_curr(1,i+1) P_left_curr(1,i) P_center_curr(1,i)]; y_l = [P_center_curr(2,i) P_center_curr(2,i+1) P_left_curr(2,i+1) P_left_curr(2,i) P_center_curr(2,i)]; z_l = [P_center_curr(3,i) P_center_curr(3,i+1) P_left_curr(3,i+1) P_left_curr(3,i) P_center_curr(3,i)]; % 右面板坐标 - Right panel coordinates x_r = [P_center_curr(1,i) P_center_curr(1,i+1) P_right_curr(1,i+1) P_right_curr(1,i) P_center_curr(1,i)]; y_r = [P_center_curr(2,i) P_center_curr(2,i+1) P_right_curr(2,i+1) P_right_curr(2,i) P_center_curr(2,i)]; z_r = [P_center_curr(3,i) P_center_curr(3,i+1) P_right_curr(3,i+1) P_right_curr(3,i) P_center_curr(3,i)]; % 绘制和填充面板 - Draw and fill panels plot3(x_l, y_l, z_l, '.-', 'LineWidth', 1, 'Color', colors(fold_idx,:)); plot3(x_r, y_r, z_r, '-', 'LineWidth', 1, 'Color', colors(fold_idx,:)); % 填充颜色 - Fill color fill3(x_l, y_l, z_l, colors(fold_idx,:)); fill3(x_r, y_r, z_r, colors(fold_idx,:)); end end % 设置图形属性 - Set figure properties xlabel('X 坐标 - X Coordinate'); ylabel('Y 坐标 - Y Coordinate'); zlabel('Z 坐标 - Z Coordinate'); title(sprintf('多折痕曲纹折纸机构 (%d 条折痕) - Multi-fold Curved Origami (%d folds)', N_folds, N_folds)); grid on; view(3) % view(0,90); % 添加图例 - Add legend legend_entries = cell(N_folds, 1); for fold_idx = 1:N_folds legend_entries{fold_idx} = sprintf('折痕 %d - Fold %d', fold_idx, fold_idx); end %% 验证几何一致性 - Verify geometric consistency fprintf('\n=== 几何一致性验证 - Geometric Consistency Verification ===\n'); for fold_idx = 1:N_folds P_center_curr = P_center_all{fold_idx}; P_right_curr = P_right_all{fold_idx}; % 计算共面性检验 - Calculate coplanarity test triple_scalars = zeros(1, length(P_center_curr)-1); for i_ = 1:length(P_center_curr)-1 P1 = P_center_curr(:,i_); P2 = P_center_curr(:,i_+1); P3 = P_right_curr(:,i_); P4 = P_right_curr(:,i_+1); % 计算混合积 - Calculate scalar triple product v1 = P2 - P1; v2 = P3 - P1; v3 = P4 - P1; triple_scalars(i_) = dot(v1, cross(v2, v3)); end % 输出验证结果 - Output verification results max_deviation = max(abs(triple_scalars)); fprintf('折痕 %d: 最大共面偏差 = %.2e - Fold %d: Max coplanarity deviation = %.2e\n', ... fold_idx, max_deviation, fold_idx, max_deviation); if max_deviation < 1e-10 fprintf(' ✓ 几何一致性良好 - Good geometric consistency\n'); else fprintf(' ⚠ 存在几何偏差 - Geometric deviation detected\n'); end end % %% 角度分析 - Angle analysis % figure(123); % clf; % hold on; % % for fold_idx = 1:N_folds % if fold_idx > 1 % % 计算角度变化 - Calculate angle changes % P_center_curr = P_center_all{fold_idx}; % P_left_curr = P_left_all{fold_idx}; % % angles_th2 = zeros(1, length(P_center_curr)-1); % angles_th3 = zeros(1, length(P_center_curr)-1); % % for i_ = 1:length(P_center_curr)-1 % A = (P_center_curr(:,i_+1) - P_center_curr(:,i_)); % B = (P_left_curr(:,i_) - P_center_curr(:,i_)); % % dot_product = dot(A, B); % norm_A = norm(A); % norm_B = norm(B); % cos_theta = dot_product / (norm_A * norm_B); % % if i_ == 1 % angles_th2(i_) = acos(cos_theta); % angles_th3(i_) = 0; % else % B1 = (P_left_curr(:,i_+1) - P_center_curr(:,i_+1)); % dot_product1 = dot(-A, B1); % norm_B1 = norm(B1); % cos_theta1 = dot_product1 / (norm_A * norm_B1); % % angles_th2(i_) = acos(cos_theta); % angles_th3(i_) = acos(cos_theta1); % end % end % % % 绘制角度变化 - Plot angle changes % plot(rad2deg(angles_th2), 'o-', 'LineWidth', 2, 'Color', colors(fold_idx,:), ... % 'DisplayName', sprintf('折痕 %d - θ2', fold_idx)); % plot(rad2deg(angles_th3), 's--', 'LineWidth', 2, 'Color', colors(fold_idx,:), ... % 'DisplayName', sprintf('折痕 %d - θ3', fold_idx)); % end % end % % xlabel('顶点索引 - Vertex Index'); % ylabel('角度 (度) - Angle (degrees)'); % title('多折痕角度分析 - Multi-fold Angle Analysis'); % legend('show'); % grid on; %% 输出总结信息 - Output summary information fprintf('\n=== 计算总结 - Calculation Summary ===\n'); fprintf('总折痕数量 - Total number of folds: %d\n', N_folds); fprintf('每条折痕顶点数 - Vertices per fold: %d\n', N_vertices); fprintf('计算完成 - Calculation completed successfully\n'); end fprintf('\n多折痕曲纹折纸机构建模完成!- Multi-fold curved origami modeling completed!\n'); %% === 添加代码:整合所有点坐标到单一矩阵 === % 计算总点数 (每条折痕有3类点 * N_vertices个顶点) totalPoints = N_folds * N_vertices * 3; % 初始化坐标矩阵 (3行: x,y,z; totalPoints列) allPointsMatrix = zeros(3, totalPoints); % 当前索引指针 currentIdx = 1; % 遍历所有折痕 for foldIdx = 1:N_folds % 当前折痕的点集 P_center = P_center_all{foldIdx}; P_left = P_left_all{foldIdx}; P_right = P_right_all{foldIdx}; % 将中心点添加到矩阵 allPointsMatrix(:, currentIdx:currentIdx+N_vertices-1) = P_left; currentIdx = currentIdx + N_vertices; % 将左边界点添加到矩阵 allPointsMatrix(:, currentIdx:currentIdx+N_vertices-1) = P_center; currentIdx = currentIdx + N_vertices; % 将右边界点添加到矩阵 allPointsMatrix(:, currentIdx:currentIdx+N_vertices-1) = P_right; currentIdx = currentIdx + N_vertices; end allPointsMatrix=allPointsMatrix'; %save('shuju.txt','allPointsMatrix','-ascii') %save('shuju2.txt','allPointsMatrix','-ascii') save('shujuf1.mat','allPointsMatrix')
最新发布
06-21
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值