zoukankan      html  css  js  c++  java
  • hdu2833 Floyd + dp

    题意:
         给你一个无向图,给你两组起点和终点,问你这两组起点和终点的最短路上最多有多少个交点...

    思路:
         开一个数组dp[i][j]记录最短路上i,j之间的点有多少个,这个数组是根据map[][]数组
    更新的时候更新的,在floyd里,当map[i][j] > map[i][k] + map[k][j] 时,
    map[i][j] = map[i][k] + map[k][j] 同时 dp[i][j] = dp[i][k] + dp[k][j] - 1;
    值得注意的是只有当i,j都是最短路上的点的时候dp[i][j]才有意义,否则里面的数字没意义,跑完Floyd以后dp里面的数组也就更新好了,然后暴力枚举每一条同时都在两条最短路上的点,取最大的那个就行了,提示:

    当 map[s0][i] + map[i][j] + map[j][e0] == map[s0][e0] 

    &&map[s1][i] + map[i][j] + mao[j][e1] == map[s1][e1] 的时候就说明i,j这两个点同时在两条最短路上.则 ans = maxx(ans ,dp[i][j]);



    #include<stdio.h>
    #include<string.h>
    
    #define N 300 + 50
    #define INF 1000000000 
    
    int map[N][N];
    int dp[N][N];
     
    void Floyd(int n)
    {
       for(int k = 1 ;k <= n ;k ++)
       for(int i = 1 ;i <= n ;i ++)
       for(int j = 1 ;j <= n ;j ++)
       {
          if(map[i][j] > map[i][k] + map[k][j])
          {
             map[i][j] = map[i][k] + map[k][j];
             dp[i][j] = dp[i][k] + dp[k][j]  - 1;
          }
       }
       return ;
    }
    
    bool ok(int s0 ,int e0 ,int s1 ,int e1 ,int i ,int j)
    {
       return map[s0][i] + map[i][j] + map[j][e0] == map[s0][e0]
       && map[s1][i] + map[i][j] + map[j][e1] == map[s1][e1];
    }
       
    int main ()
    {
       int n ,m ,i ,j;
       int a ,b ,c;
       int s0 ,s1 ,e1 ,e0;
       while(~scanf("%d %d" ,&n ,&m) && n + m)
       {
          for(i = 1 ;i <= n ;i ++)
          {
             for(j = i + 1 ;j <= n ;j ++)
             map[i][j] = map[j][i] = INF ,dp[i][j] = 0;
             map[i][i] = 0 ,dp[i][i] = 1;
          }
                
          for(i = 1 ;i <= m ;i ++)
          {
             scanf("%d %d %d" ,&a ,&b ,&c);
             if(map[a][b] > c) map[a][b] = map[b][a] = c;
             dp[a][b] = dp[b][a] = 2;
          }
          
          scanf("%d %d %d %d" ,&s0 ,&e0 ,&s1 ,&e1);
          Floyd(n);
          int ans = 0;
          for(i = 1 ;i <= n ;i ++)
          for(j = 1 ;j <= n ;j ++)
          if(ok(s0 ,e0 ,s1 ,e1 ,i ,j) && ans < dp[i][j])
          ans = dp[i][j]; 
          printf("%d
    " ,ans);
       }
       return 0;
       
    }
          
    

  • 相关阅读:
    Delphi中TFlowPanel实现滚动条效果
    Delphi组件开发-在窗体标题栏添加按钮(使用MakeObjectInstance(NewWndProc),并处理好多消息)
    减小Delphi的Exe文件大小(11种方法)
    画出太极图
    类似地图的以鼠标为中心缩放图像
    andoid x项目的优化 1
    ICON图标文件解析
    所有语言的Awesome(2)
    获取EIP(汇编语言直接给Delphi变量赋值)
    Qt Windows下链接子系统与入口函数(终结版)(可同时存在main和WinMain函数)
  • 原文地址:https://www.cnblogs.com/csnd/p/12063194.html
Copyright © 2011-2022 走看看