TOJ 3883: Roadblock -- 单源最短路

3883: Roadblock

Time Limit(Common/Java):1000MS/3000MS     Memory Limit:65536KByte
Total Submit: 17            Accepted:7

Description

Every morning, FJ wakes up and walks across the farm from his house to the barn. The farm is a collection of N fields (1 <= N <= 100) connected by M bidirectional pathways (1 <= M <= 10,000), each with an associated length. FJ's house is in field 1, and the barn is in field N. No pair of fields is joined by multiple redundant pathways, and it is possible to travel between any pair of fields in the farm by walking along an appropriate sequence of pathways. When traveling from one field to another, FJ always selects a route consisting of a sequence of pathways having minimum total length.

Farmer John's cows, up to no good as always, have decided to interfere with FJ's morning routine. They plan to build a pile of hay bales on exactly one of the M pathways on the farm, doubling its length. The cows wish to select a pathway to block so that they maximize the increase in FJ's distance from the house to the barn. Please help the cows determine by how much they can lengthen FJ's route.

Input

* Line 1: Two space-separated integers, N (1 <= N <= 100) and M (1 <= M <= 10,000).

* Lines 2..1+M: Line j+1 describes the jth bidirectional pathway in terms of three space-separated integers: A_j B_j L_j, where A_j and B_j are indices in the range 1..N indicating the fields joined by the pathway, and L_j is the length of the pathway (in the range 1...1,000,000).

Output

* Line 1: The maximum possible increase in the total length of FJ's shortest route made possible by doubling the length of a single pathway.

Sample Input

5 7
2 1 5
1 3 1
3 2 8
3 5 7
3 4 3
2 4 7
4 5 2

Sample Output

2

Hint

INPUT DETAILS:

There are 5 fields and 7 pathways. Currently, the shortest path from the house (field 1) to the barn (field 5) is 1-3-4-5 of total length 1+3+2=6.

OUTPUT DETAILS:

If the cows double the length of the pathway from field 3 to field 4 (increasing its length from 3 to 6), then FJ's shortest route is now 1-3-5, of total length 1+7=8, larger by two than the previous shortest route length.

Source

USACO Dec. 2011


分析:先求出点1和点n到其他点的最短距离(两次Dijkstra),以便后面判断某条边是否在最短路径上。然后枚举每一条边(i, j),判断该边是否在某一条最短路径上,如果是,计算加倍该边之后新的最短路径长度。枚举时只需要枚举比当前答案大的边,因为加倍该边后,即使走原路,最短路径长度也只增加该边长度。

#include 
     
     
      
      
#include 
      
      
       
       
#include 
       
       
        
        
#include 
        
        
         
         
#include 
         
         
           #include 
           #include 
           
             #include 
            
              #include 
             
               #include 
              
                #include 
               
                 #include 
                
                  #include 
                 
                   #include 
                  
                    #include 
                   
                     #include 
                    
                      #define mp make_pair using namespace std; typedef unsigned int ui; typedef long long ll; typedef unsigned long long ull; typedef pair 
                     
                       pii; typedef vector 
                      
                        vi; typedef vi::iterator vi_it; typedef map 
                       
                         mii; typedef priority_queue 
                        
                          pqi; typedef priority_queue 
                         
                           , greater 
                          
                            > rpqi; typedef priority_queue 
                           
                             , greater 
                            
                              > rpq_pair; const int MAX_N = 100 + 2; const int INF = (int)1.0e9; int dis[MAX_N][MAX_N]; int lowcost[2][MAX_N]; int lowcost_tmp[MAX_N]; bool vis[MAX_N]; class Dijkstra { public: void dijkstra(int *d, int n, int s); private: void relax(int *d, int u, int v, int w, rpq_pair &q); void initialize_single_source(int *d, int n, int s); }; void Dijkstra::initialize_single_source(int *d, int n, int s) { for (int i = 1; i <= n; ++i) { d[i] = INF; } d[s] = 0; } void Dijkstra::relax(int *d, int u, int v, int w, rpq_pair &q) { if (d[u] > d[v] + w) { d[u] = d[v] + w; q.push(mp(d[u], u)); } if (d[v] > d[u] + w) { d[v] = d[u] + w; q.push(mp(d[v], v)); } } void Dijkstra::dijkstra(int *d, int n, int s) { initialize_single_source(d, n, s); memset(vis, 0, sizeof(vis)); rpq_pair q; int i, j; for (i = 1; i <= n; ++i) { q.push(mp(d[i], i)); } for (i = 1; i <= n; ++i) { pii p; do { p = q.top(); q.pop(); } while (vis[p.second]); vis[p.second] = true; for (j = 1; j <= n; ++j) { if (!vis[j] && dis[p.second][j] != -1) { relax(d, p.second, j, dis[p.second][j], q); } } } } int main(int argc, char *argv[]) { // freopen("D:\\in.txt", "r", stdin); int n, m; cin >> n >> m; memset(dis, -1, sizeof(dis)); while (m--) { int a, b, c; cin >> a >> b >> c; dis[a][b] = dis[b][a] = c; } Dijkstra dij; dij.dijkstra(lowcost[0], n, 1); dij.dijkstra(lowcost[1], n, n); int pre = lowcost[0][n]; int ans = 0; for (int i = 1; i <= n; ++i) { for (int j = i + 1; j <= n; ++j) { if (dis[i][j] > ans && min(lowcost[0][i] + lowcost[1][j], lowcost[0][j] + lowcost[1][i]) + dis[i][j] == pre) { dis[i][j] = dis[j][i] = dis[j][i] << 1; dij.dijkstra(lowcost_tmp, n, 1); ans = max(ans, lowcost_tmp[n] - pre); dis[i][j] = dis[j][i] = dis[j][i] >> 1; } } } cout << ans << endl; return 0; } 
                             
                            
                           
                          
                         
                        
                       
                      
                     
                    
                   
                  
                 
                
               
              
             
            
         
        
        
       
       
      
      
     
     

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值