poj 3662 Telephone Lines

很棒的题目. 简单来说,本题是在无向图上求一条1到N的路径, 使路径上第 K + 1 大的边权尽量小.

本题答案显然有单调性,支付的钱更多时,合法的升级方案一定包含话费少的方案.

于是考虑二分.把升级价格不超过 mid 的边的长度设为0, 然后求从 1 到 N 的最短路长度是否不超过 K 即可.

  1 #include <cstdio>
  2 #include <algorithm>
  3 #include <cstring>
  4 #include <queue>
  5 #include <vector>
  6 #include <iostream>
  7 
  8 using namespace std;
  9 typedef pair<int, int> Pa;
 10 const int MAXN = 1e3 + 20;
 11 const int MAXP = 1e4 + 20;
 12 const int MAXL = 1000000 + 20;
 13 
 14 inline int read()
 15 {
 16     int x = 0; char ch = getchar();
 17     while(!isdigit(ch)) ch = getchar();
 18     while(isdigit(ch)) x = x * 10 + ch - '0', ch = getchar();
 19     return x;
 20 }
 21 
 22 int N, P, K;
 23 
 24 namespace edges
 25 {
 26     struct edge
 27     {
 28         int from, to, cost;
 29         edge(int u = 0, int v = 0, int c = 0) : from(u), to(v), cost(c) {}
 30 
 31         bool operator <(const edge &rhs) const{
 32             return cost < rhs.cost;
 33         }
 34     }E[MAXP];
 35 
 36     inline void addedge(int u, int v, int c)
 37     {
 38         static int cnt = 1;
 39         E[cnt++] = edge(u, v, c);
 40     }
 41 
 42     inline void init()
 43     {
 44         sort(E + 1, E + P + 1);
 45     }
 46 }
 47 
 48 namespace dij
 49 {
 50     struct edge
 51     {
 52         int to, cost;
 53         edge(int v = 0, int c = 0) : to(v), cost(c) {}
 54     };
 55 
 56     vector<edge> g[MAXN];
 57     int d[MAXN];
 58 
 59     inline void addedge(int u, int v, int c)
 60     {
 61         g[u].push_back(edge(v, c));
 62         g[v].push_back(edge(u, c));
 63     }
 64 
 65     inline void init()
 66     {
 67         for(int i = 0; i <= N; i++)
 68             g[i].clear();
 69     }
 70 
 71     inline bool tension(const int &sml, int &big)
 72     {
 73         return sml < big ? (big = sml, true) : false;
 74     }
 75 
 76     inline int dijkstra(int s, int t)
 77     {
 78         deque<Pa> q;
 79         memset(d, 0x3f, sizeof(d));
 80 
 81         d[s] = 0;
 82         q.push_front(Pa(0, s));
 83 
 84         while(!q.empty())
 85         {
 86             Pa p = q.front(); q.pop_front();
 87             int u = p.second;
 88             if(d[u] < p.first) continue;
 89 
 90             for(int i = 0; i < (int) g[u].size(); i++)
 91             {
 92                 edge e = g[u][i];
 93                 if(tension(d[u] + e.cost, d[e.to]))
 94                 {
 95                     if(e.cost == 1) q.push_back(Pa(d[e.to], e.to));
 96                     else q.push_front(Pa(d[e.to], e.to));
 97                 }
 98             }
 99         }
100         return d[t];
101     }
102 }
103 
104 inline bool check(int fare)
105 {
106     using namespace edges;
107 
108     dij::init();
109     for(int i = 1; i <= P; i++)
110     {
111         edge e = E[i];
112         dij::addedge(e.from, e.to, e.cost > fare ? 1 : 0);
113     }
114 
115     return dij::dijkstra(1, N) > K ? false : true;
116 }
117 
118 int main()
119 {
120 //    freopen("p1948.txt", "r", stdin);
121     cin>>N>>P>>K;
122 
123     int u, v;
124     for(int i = 1; i <= P; i++)
125     {
126         u = read(), v = read();
127         edges::addedge(u, v, read());
128     }
129 
130     //edges::init();
131 
132     int l = 0, r = MAXL;
133     #define mid (((l) + (r)) >> 1)
134     while(l < r)
135     {
136         if(check(mid)) r = mid;
137         else l = mid + 1;
138     }
139 
140     if(l == MAXL) cout<<-1<<endl;
141     else cout<<l<<endl;
142     return 0;
143 }

 

猜你喜欢

转载自www.cnblogs.com/wsmrxc/p/8994772.html