【问题标题】:minimum penalty path in weighted graph加权图中的最小惩罚路径
【发布时间】:2016-06-14 10:27:31
【问题描述】:

考虑一个包含 N 个节点和 M 个边的无向图。每条边 Mi 都有一个整数成本,Ci,与之相关。

路径的惩罚是一对节点 AB 之间路径中每个边成本的按位或。换句话说,如果路径包含边 M1,M2,..., Mk 那么这条路径的惩罚是 C1 OR C2 OR ... OR Ck.

给定一个图和两个节点 AB,找到 AB 之间的路径最小可能的处罚并打印其处罚;如果不存在这样的路径,则打印−1 表示不存在从AB 的路径。

注意:允许使用循环和多重边。

约束:

1≤N≤103

1≤M≤103

1≤Ci

1≤Ui,ViN

1≤A,BN

AB

这个问题是在比赛中提出的,它结束了我浏览了教程但无法得到它。谁能解释或给出答案如何进行?

【问题讨论】:

    标签: algorithm graph language-agnostic dynamic-programming


    【解决方案1】:
    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef pair <ll,ll > pr;
    vector <pr> adj[10005];
    bool visited[10005][10005];
    int main(){
        ll n,m;
        scanf("%lld%lld",&n,&m);
        for(ll i=1;i<=m;i++){
            ll u,v,w;
            scanf("%lld%lld%lld",&u,&v,&w);
            adj[u].push_back(make_pair(v,w));
            adj[v].push_back(make_pair(u,w));
        }
        ll source,destination;
        scanf("%lld%lld",&source,&destination);
        queue<ll> bfsq;
        bfsq.push(source);// source into queue
        bfsq.push(0);// 
        while(!bfsq.empty()){
        ll u=bfsq.front();
            bfsq.pop();
            ll cost=bfsq.front();
            bfsq.pop();
            visited[u][cost]=true;
            for(ll i=0;i<adj[u].size();i++){
              ll  v=adj[u][i].first;// neighbor of u is v
              ll  w2=adj[u][i].second;//// u is connected to v with this cost
              if(visited[v][w2|cost]==false){
                visited[v][w2|cost]=true;
                bfsq.push(v);
                bfsq.push(w2|cost);
    
    
              }
            }
        }
        ll ans=-1LL;
        for(ll i=0;i<1024;i++){
            if(visited[destination][i]==true){
                ans=i;
                break;
            }
        }
        printf("%lld\n",ans);
        return 0;
    
    }
    

    【讨论】:

      【解决方案2】:

      可以通过以下递归公式使用动态规划来解决:

      D(s,0) = true
      D(v,i) = false OR D(v,i) OR { D(u,j) | (u,v) is an edge, j or c(u,v) = i }
      

      s 是源节点。

      这个想法是D(v,i) == true 当且仅当存在从sv 且权重正好为i 的路径。
      现在,您在动态规划中迭代地修改图形,直到它收敛(最多在 n 迭代之后)。
      这基本上是Bellman-Ford algorithm 的变体。 为解决方案创建 DP 表后,最小路径为 min { x | D(t,x) = true}(其中 t 是目标节点)。

      时间复杂度为O(m*n*log_2(R)),其中R 是允许的最大权重(在您的情况下为1024)。

      【讨论】:

      • 你能详细说明一下吗?
      • @rj124 我添加了一些说明,希望清楚。
      • 不能用dijkstra算法完成吗?在放松边缘的同时,我们可以使用当前边缘权重计算到目前为止的|of 路径距离,并将其插入到最小优先级队列中。
      【解决方案3】:

      您正在寻找的是Dijkstra's Algorithm。与其为每个节点添加权重,不如对其进行 ORing。

      因此,伪代码如下(根据维基百科示例修改):

       1  function Dijkstra(Graph, source):
       2
       3      create vertex set Q
       4
       5      for each vertex v in Graph:             // Initialization
       6          dist[v] ← INFINITY                  // Unknown distance from source to v
       7          prev[v] ← UNDEFINED                 // Previous node in optimal path from source
       8          add v to Q                          // All nodes initially in Q (unvisited nodes)
       9
      10      dist[source] ← 0                        // Distance from source to source
      11      
      12      while Q is not empty:
      13          u ← vertex in Q with min dist[u]    // Source node will be selected first
      14          remove u from Q 
      15          
      16          for each neighbor v of u:           // where v is still in Q.
      17              alt ← dist[u] OR length(u, v)
      18              if alt < dist[v]:               // A shorter path to v has been found
      19                  dist[v] ← alt 
      20                  prev[v] ← u 
      21
      22      return dist[], prev[]
      

      注意第 17 行的 OR。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-04-01
        • 2016-07-13
        • 1970-01-01
        • 2021-04-10
        • 1970-01-01
        • 2014-12-01
        相关资源
        最近更新 更多