sdut 2493 Constructing Roads (图论)

http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2493

好纠结 这么道  破题  比赛是竟然 没做出来  ,比赛 完后  加了个 条件就对了 ,为什么 比赛时 那么 没状态   。。。。。。。。。。。

题意:给出一个无向图  ,一个 原点 s  一个终点  t  求 一条 最短的路径 值 从 s 到 t  ,对于 这条路径  可以 将  其中的 一条边的权值 减半。

题解 :  dij +  枚举

   首先  我们可以 得到 知道   对于 t  来说  最小值  = min(与他 连接的点的 最小值  +  w[i][t],    s 到  i  的 最短距离   +  w[i][t] / 2) ;

 所以 我们 得到 状态方程 

   dp[i] 记录  i  的  最终解  dis[i]记录  最短路径 

    设  x  与  i  相连

    dp[i] = min(dp[i] ,min(dp[x] + w[i][x],dis[x] + w[i][x] / 2)) ;

View Code
  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cmath>
  4 #include<iostream>
  5 #include<algorithm>
  6 #include<set>
  7 #include<map>
  8 #include<queue>
  9 #include<vector>
 10 #include<string>
 11 #define inf 99999999
 12 #define maxn 1500
 13 #define CL(a,b) memset(a,b,sizeof(a))
 14 #define  ll  long long
 15 //#define mx 1000010
 16 using namespace std;
 17 int n , m ;
 18 int s,t ;
 19 int dis[maxn],vis[maxn],pre[maxn] ;
 20 int mat[maxn][maxn] ;
 21 int dp[maxn] ;
 22 int solve(int s,int t)
 23 {
 24     int i , j ;
 25     for(i = 0;i<= n;i++)
 26     {
 27         dis[i] = mat[s][i] ;
 28     }
 29     dis[s] = 0 ;
 30 
 31 
 32     CL(vis,0) ;
 33 
 34 
 35 
 36     int k ;
 37     for(i = 0 ; i < n;i++)
 38     {
 39         int mi = inf ;
 40         k = 0 ;
 41         for(j = 1 ; j <= n;j++)
 42         {
 43             if(!vis[j]&& dis[j] != inf && dis[j] < mi)
 44             {
 45                 mi = dis[j] ;
 46                 k =  j ;
 47             }
 48         }
 49 
 50         if(k == 0break ;
 51 
 52         vis[k] = 1 ;
 53 
 54 
 55         for(j = 1 ; j <= n;j++)
 56         {
 57             if(!vis[j] && mat[k][j] != inf && dis[j] > dis[k] + mat[k][j])
 58             {
 59 
 60                 dis[j] = dis[k] +  mat[k][j] ;
 61 
 62             }
 63         }
 64     }
 65 
 66 
 67 
 68 
 69 
 70     if(dis[t] >= inf) return -1 ;
 71 
 72 
 73     for(i = 0; i<= n;i++)
 74     {
 75         dp[i] = mat[s][i];
 76     }
 77 
 78     dp[s] = 0 ;
 79 
 80     for(i = 1; i <= n;i++)
 81     {
 82 
 83         for(j = 1; j <= n;j++)
 84         {
 85             if(j == s||i == j)continue ;
 86             if(mat[i][j]!=inf)
 87             {
 88                 dp[j] = min(dp[j],min(dp[i] + mat[i][j] ,dis[i] + mat[i][j]/2)) ;
 89             }
 90         }
 91     }
 92 
 93     return dp[t] ;
 94 
 95 
 96 }
 97 int main()
 98 {
 99     int i , j,u,v,w  ;
100     while(scanf("%d%d",&n,&m)!=EOF)
101     {
102 
103         for(i = 0; i <= n;i++)
104         {
105             for(j = 0 ; j <= n;j++)
106              mat[i][j] = mat[j][i] = inf ;
107 
108             mat[i][i] = 0 ;
109         }
110 
111         for(i = 0; i < m;i++)
112         {
113             scanf("%d%d%d",&u,&v,&w);
114             if(w < mat[u][v])
115             mat[u][v] = mat[v][u] = w ;
116         }
117         scanf("%d%d",&s,&t) ;
118         int ans = solve(s,t) ;
119 
120         if(ans == -1)printf("No solution\n");
121         else
122             printf("%d\n",ans) ;
123     }
124 }
原文地址:https://www.cnblogs.com/acSzz/p/2798489.html