zoukankan      html  css  js  c++  java
  • hdu4370 比较抽象的最短路

    题意:
          给你一个n*n的矩阵,然后让咱们构造另一个n*n的矩阵,构造的矩阵有如下要求,
    1.X12+X13+...X1n=1.
    2.X1n+X2n+...Xn-1n=1.
    3.for each i (1<i<n), satisfies ∑Xki (1<=k<=n)=∑Xij (1<=j<=n).

    思路:

          感觉这个思路很奇葩啊,看了网上好多解释,但是很失望啊,几乎所有人说的都一样啊,一样到几乎不差一个字,我就 呵呵了,说实话这个题目我不是很理解,可以说现在并不是很明白,但是我可以说下我现在对他们的做法的一些理解,可能不全面,也可能有错误,希望路过的大牛指点,首先据说这是个0/1规划问题,我只知道0/1分数规划,不知道什么是0/1规划,而且具我的了解这个题目跟0/1分数规划没啥关系,我们现在就往图论上靠一下,首先虚拟出n个点来,记住这n个点不是行,也不是列,把题目给的矩阵就单独当成是一些数据,一些点之间的距离,不要去往矩阵上想,这样便于理解,然后分析它给的三个条件:


    1.X12+X13+...X1n=1. 这个条件可以理解成是点1的出度为1,因为1会选择也只能选择一个点连出去,这样的话1的出度为0.


    2.X1n+X2n+...Xn-1n=1. 同上,n的入度为0.

    3.for each i (1<i<n), satisfies ∑Xki (1<=k<=n)=∑Xij (1<=j<=n).这个说的是除了1,n外,所有的点的入度和出度都相等。

    这样,突然就想到了图的特点,这样我们想象一下,超级原点1,超级汇点n,中间所有的都是入度等于出度,让我们找一个最小的花费满足上面的3点要求,而且最关键的是所有点的权值都是 >= 0的,这样我们就可以用最短路去跑了,直接跑1->n之间的最短路,可能有人想,跑最短路不是直接就默认中间的点的部分所有的入度和出度都是1了?没错,所有的都是1,因为想象一下,能用1就满足题意了,还有必要再多跑吗?这个地方不要想矩阵的问题,不然很容易蒙的,这样我们跑出最短路c,这个是一种情况,还有另一种情况就是可以直接从1跑一个最小环得到花费c1,然后从n跑一个环得到最小花费c2,两个环也满足上面的三个限制,这样我们只要输出min(c ,c1 + c2)就行了,对了还有一个差点忘记说了,至于找最小花费环,方法很多,可以直接搜索,说一个对于这个题目比较简单的方法(在网上看的!嘿嘿),我们可以在跑最短路的时候先把起始点入队,把起始点连接的所有点入队,这样跑完

    之后,到起始点的最短距离就是最小环了(具体看代码),以上就是我对网上题解的理解,目前只有这些,可能不对,很希望能和看到的人一起交流研究这个题目。


    #include<stdio.h>
    #include<string.h>
    #include<queue>
    
    #define N_node 330
    #define INF 1000000000
    
    using namespace std;
    
    int cost[N_node][N_node];
    int  s_x[N_node] ,mark[N_node];
    
    void spfa(int s ,int n)
    {
       for(int i = 0 ;i <= n ;i ++)
       s_x[i] = INF ,mark[i] = 0;
       queue<int>q;
       for(int i = 1 ;i <= n ;i ++)
       {
          if(s == i) continue;
          s_x[i] = cost[s][i];
          mark[i] = 1;
          q.push(i);
       }
       while(!q.empty())
       {
          int xin ,tou;
          tou = q.front();
          q.pop();
          mark[tou] = 0;
          for(int i = 1 ;i <= n ;i ++)
          {
             xin = i;
             if(s_x[xin] > s_x[tou] + cost[tou][xin])
             {
                s_x[xin] = s_x[tou] + cost[tou][xin];
                if(!mark[xin])
                {
                   mark[xin] = 1;
                   q.push(xin);
                }
             }
          }
       }
    }
    
    int main ()
    {
       int i ,j ,n;
       while(~scanf("%d" ,&n))
       {
          for(i = 1 ;i <= n ;i ++)
          for(j = 1 ;j <= n ;j ++)
          scanf("%d" ,&cost[i][j]);
          spfa(1 ,n);
          int Ans = s_x[n];
          int c1 = s_x[1];
          spfa(n ,n);
          int c2 = s_x[n];
          if(Ans > c1 + c2) Ans = c1 + c2;
          printf("%d
    " ,Ans);
       }
       return 0;
    }
          
          
          
    

  • 相关阅读:
    深入了解抽象类和接口
    关于Hibernate查询对象调用set方法自动同步到数据库解决方案
    【鸽子的迷信(一)】python导入由excel文件改后缀变成的csv文件出现乱码错误(ParserError:Error tokenizing data. C error:)
    《计算机操作系统》CH1操作系统引论思维导图整理
    IntelliJ IDEA创建一个Maven项目
    C++实验三
    小练习
    C++实验二
    C++的ch1&ch2的整理
    C++实验一
  • 原文地址:https://www.cnblogs.com/csnd/p/12062767.html
Copyright © 2011-2022 走看看