• hdu 4370 0 or 1 (最短路 // 01 规划 2012 MultiUniversity Training Contest 8 )


    http://acm.hdu.edu.cn/showproblem.php?pid=4370

    题解:   http://page.renren.com/601081183/note/866168965

     

    好一道转换思维的题啊,由一道,让人 不知如何下手的题,转换为了 最短路,问题,经典。。。。

    我们没有想到啊,看了题解才知道,,思维有点局限啊。。。。

    1001  (已更新)

    显然,题目给的是一个0/1规划模型。

    解题的关键在于如何看出这个模型的本质。

    3个条件明显在刻画未知数之间的关系,从图论的角度思考问题,容易得到下面3个结论:

    1.X12+X13+...X1n=1 于是1号节点的出度为1

    2..X1n+X2n+...Xn-1n=1 于是n号节点的入度为1

    3.∑Xki =∑Xij 于是2~n-1号节点的入度必须等于出度

    于是3个条件等价于一条从1号节点到n号节点的路径,故Xij=1表示需要经过边(i,j),代价为Cij。Xij=0表示不经过边(i,j)。注意到Cij非负且题目要求总代价最小,因此最优答案的路径一定可以对应一条简单路径。

    最终,我们直接读入边权的邻接矩阵,跑一次1到n的最短路即可,记最短路为path。

    以上情况设为A

    非常非常非常非常非常非常非常非常抱歉,简单路径只是充分条件,但不必要。(对造成困扰的队伍深表歉意)

    漏了如下的情况B:

    从1出发,走一个环(至少经过1个点,即不能是自环),回到1;从n出发,走一个环(同理),回到n。

    容易验证,这是符合题目条件的。且A || B为该题要求的充要条件。

    由于边权非负,于是两个环对应着两个简单环。

    因此我们可以从1出发,找一个最小花费环,记代价为c1,再从n出发,找一个最小花费环,记代价为c2。(只需在最短路算法更新权值时多加一条记录即可:if(i==S) cir=min(cir,dis[u]+g[u][i]))

    故最终答案为min(path,c1+c2)

    View Code
     1 #include<stdio.h>
     2 #include<iostream>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<cmath>
     6 #include<queue>
     7 #include<set>
     8 #include<map>
     9 #define Min(a,b)  a>b?b:a
    10 #define Max(a,b)  a>b?a:b
    11 #define CL(a,num)  memset(a,num,sizeof(a));
    12 #define inf 99999999
    13 #define maxn    500
    14 #define mod 100000007
    15 #define eps  1e-6
    16 #define ll  long long
    17 #define M   15520
    18 using namespace std;
    19 int n,mat[maxn][maxn],vis[maxn],dis[maxn];
    20 void SPFA(int x)
    21 {
    22     int i ;
    23     queue<int>que;
    24     CL(vis,0);
    25     for( i = 1; i <= n;++i)
    26     {
    27         if(i == x)
    28         {
    29             dis[i] = inf;
    30         }
    31         else
    32         {
    33             dis[i] = mat[x][i];
    34             vis[i] = 1;
    35             que.push(i);
    36         }
    37     }
    38     while(!que.empty())
    39     {
    40         int  u = que.front(); que.pop();
    41          vis[u] = 0;
    42 
    43          for( i =1; i <= n ;++i)
    44          {
    45              if(dis[i] > dis[u] + mat[u][i])
    46              {
    47                  dis[i] = dis[u] + mat[u][i] ;
    48                  if(!vis[i])
    49                  {
    50                       que.push(i);
    51                       vis[i] = 1 ;
    52                  }
    53 
    54              }
    55          }
    56 
    57     }
    58 }
    59 int main()
    60 {
    61     int  i,j;
    62     while(scanf("%d",&n)!=EOF){
    63 
    64      for( i = 1; i <=n; ++i)
    65       for( j = 1; j <= n;++j)
    66        scanf("%d",&mat[i][j]);
    67 
    68 
    69        SPFA(1);
    70        int ans = dis[n];
    71        int c1 = dis[1] ;
    72        SPFA(n);
    73        int c2 = dis[n] ;
    74        ans = min(ans,c1+c2);
    75        printf("%d\n",ans);
    76 
    77 
    78 
    79 
    80     }
    81 }

     

     

  • 相关阅读:
    结束咯
    在Ubuntu上不能使用PPA下载
    月亮+大环
    piano
    花都论坛,广州花都本地生活
    LLVM的调用协议与内存对齐
    SALVIA 0.5.2优化谈
    LLVM随笔
    OS之争:永不停歇的战争(二,完结)
    OS之争:永不停歇的战争(一)
  • 原文地址:https://www.cnblogs.com/acSzz/p/2643566.html
Copyright © 2020-2023  润新知