You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

带权有向图满足重复约束的最大权重非简单路径求解问询

Implementing GRAPHfindPath for Constrained Maximum-Weight Paths

Hey there! Let's work through implementing the GRAPHfindPath function to meet your specific path constraints. First, let's recap the requirements clearly: we need to find the highest-weight path from vertex v1 to v2 that:

  1. Ends exactly at v2
  2. Has at least k distinct vertices that are visited more than once
  3. Has a total of at least p repeat visits (sum of all times vertices are visited beyond their first occurrence)

Since all edge weights are positive, we can't just use standard shortest-path algorithms—instead, we'll use a backtracking DFS approach to explore paths, track the necessary state, and keep track of the best valid path we find.


First, Let's Lay Out the Core Approach

The key here is to track state as we explore paths:

  • Visit counts: How many times each vertex has been visited (to calculate repeats)
  • Repeated vertex count: How many distinct vertices have been visited at least twice
  • Total repeats: Sum of all visit counts minus the number of unique vertices in the path (since first visits don't count as repeats)
  • Current path weight: Sum of edge weights along the current path
  • Current path sequence: The vertices we've visited so far

We'll use a recursive DFS to explore all possible paths from v1 to v2, backtracking to explore different branches, and updating our best path whenever we find a valid path (meeting the repeat constraints) with a higher weight than our current best.


Step-by-Step Implementation

1. Add the GRAPHfindPath Implementation to graph.c

Replace the empty GRAPHfindPath function with the following code. We'll include a helper DFS function to handle the recursive exploration.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "graph.h"
#include "ST.h"

// Forward declaration of our recursive DFS helper
static void dfs(graph_t G, int current, int target, int k, int p, int current_weight,
                int *visit_count, int repeated_vertices, int total_repeats,
                int *path, int path_len, int *best_weight, int **best_path, int *best_path_len);

void GRAPHfindPath(graph_t G, int k, int p, char *v1, char *v2) {
    // Convert input vertex strings to internal integer IDs
    int start = STsearch(G->tab, v1);
    int target = STsearch(G->tab, v2);

    // Check if vertices exist in the graph
    if (start == -1 || target == -1) {
        printf("Error: One or both vertices are not present in the graph.\n");
        return;
    }

    // Initialize tracking variables
    int *visit_count = calloc(G->V, sizeof(int)); // Tracks how many times each vertex is visited
    int *path = malloc(G->V * 100 * sizeof(int)); // Buffer for current path (adjust size as needed)
    int path_len = 0;

    int best_weight = -1; // Tracks the highest weight of valid paths found
    int *best_path = NULL; // Stores the best path sequence
    int best_path_len = 0; // Length of the best path

    // Start the DFS exploration
    dfs(G, start, target, k, p, 0, visit_count, 0, 0, path, path_len, &best_weight, &best_path, &best_path_len);

    // Output the results
    if (best_weight == -1) {
        printf("No valid path found that meets the constraints.\n");
    } else {
        printf("Best valid path (total weight: %d):\n", best_weight);
        for (int i = 0; i < best_path_len; i++) {
            // Look up the vertex name from the symbol table
            printf("%s ", G->tab->a[best_path[i]]);
        }
        printf("\n");
        printf("Constraints met: %d distinct repeated vertices, %d total repeats\n", k, p);
    }

    // Clean up allocated memory
    free(visit_count);
    free(path);
    if (best_path) free(best_path);
}

// Recursive DFS helper function
static void dfs(graph_t G, int current, int target, int k, int p, int current_weight,
                int *visit_count, int repeated_vertices, int total_repeats,
                int *path, int path_len, int *best_weight, int **best_path, int *best_path_len) {
    // Update state for current vertex
    visit_count[current]++;
    path[path_len] = current;
    path_len++;

    int new_repeated = repeated_vertices;
    int new_total = total_repeats;

    // Update repeat counters if this is the second visit to current vertex
    if (visit_count[current] == 2) {
        new_repeated++;
    }
    // Update total repeats if this is not the first visit
    if (visit_count[current] > 1) {
        new_total++;
    }

    // Check if we've reached the target vertex
    if (current == target) {
        // Verify if we meet the repeat constraints
        if (new_repeated >= k && new_total >= p) {
            // Update best path if current path has higher weight
            if (current_weight > *best_weight) {
                *best_weight = current_weight;
                // Free existing best path if it exists
                if (*best_path) free(*best_path);
                // Copy current path to best path
                *best_path = malloc(sizeof(int) * path_len);
                memcpy(*best_path, path, sizeof(int) * path_len);
                *best_path_len = path_len;
            }
        }
        // Backtrack: undo state changes for current vertex
        visit_count[current]--;
        path_len--;
        return;
    }

    // Explore all adjacent edges
    link t;
    for (t = G->adj_l[current]; t != G->z; t = t->next) {
        int next_v = t->v;
        int new_weight = current_weight + t->wt;

        // Optional pruning: if current path can't possibly exceed best weight, skip
        // Since all weights are positive, we can skip this for now (add later for optimization)

        // Recurse to next vertex
        dfs(G, next_v, target, k, p, new_weight, visit_count, new_repeated, new_total,
            path, path_len, best_weight, best_path, best_path_len);
    }

    // Backtrack: undo state changes for current vertex
    visit_count[current]--;
    path_len--;
}

Key Notes & Optimizations

  1. Memory Management: The path buffer is sized to G->V * 100 to accommodate long paths, but you can adjust this or use dynamic reallocation (realloc) if you expect extremely long paths.
  2. Pruning: Since all edge weights are positive, we can optimize by precomputing the maximum-weight cycle in the graph. If the current path weight plus the cycle weight multiplied by a reasonable number of loops is still less than the current best weight, we can stop exploring that branch—this will significantly speed up the search for large graphs.
  3. Stack Overflow: For very deep paths, recursive DFS might cause stack overflow. If this is an issue, you can rewrite the DFS using an iterative approach with a stack data structure.
  4. Edge Cases: Make sure to test cases where v1 == v2 (paths that start and end at the same vertex, with repeats), or where no valid path meets the repeat constraints.

内容的提问来源于stack exchange,提问作者Vincenzo Cosi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:54:11