Code Hourse

CodeForces 449B - Jzzhu and Cities

传送门:Jzzhu and Cities

 

题意:

题意一定要看仔细,这里说一个国家,有N个城市,城市与城市之间有M条路,距离为W,编号为1的城市是首都,1和K个城市有火车道,距离为X

现在国家要节省开支,想把其中部分铁路关闭,但是又想关闭之后从首都到每一个城市本来的最短距离不变,求最多能关闭多少条铁路。

 

分析:

注意最重要的几点:

1、求关闭最多的铁路

2、关闭之后,从首都到每一个城市的最短距离不变。

3、从首都到某个城市的铁路可能有多条

 

算法:

很明显,求最短距离不变,那么就是最短路径问题,DIJK算法用上。

从首都到某个城市,有两种方式

1、走路

2、坐火车

但是为了节省,如果走路的距离==坐火车,那么这条火车道就干掉。

那么好了,知道这点,我们就必须先求走路的距离,再求一下坐火车的距离,判断一下是否相等就可以了。

如果火车比走路更远,干掉。

但是要注意一点:

可能从首都有多条铁路到某一个城市,那么一定一定要想到,我们只需要最短那条铁道来判断,其他比他远的,留来干嘛!!!!(我这里没判重,坑了好久)。

接下来就是第二点:

从首都到某个城市的距离,我们中途是可以坐火车的!!!!那么这个距离可能跟你从首都直接坐火车到这个城市的距离相等,这条铁路也得干掉!!!!(第二个坑)

 

好了,现在就可以求最多多少条了。

 

首先,最短路径,先去掉所有铁路求一次,那么就得到从首都走路到其他城市的所有最短距离

 

再把铁路全部加上,那么就求到(可能)加上坐火车到其他城市的最短距离。

 

之后就是判断,这条铁路是否需要就可以了。

 

判断的依据是,在DIJK算法里面加一个pre[v] = u ,记录v是从u这个城市过来的。

 

转移的时候,如果u是首都1,并且存在一个u',跟从首都1直接坐火车到v的距离相等,那么我们就抛弃从首都坐火车这条,改为从首都到 u'再走路过来v这条路,那么就又少一条铁路了。

 

之后把这些情况加上,就是最多能删多少条铁路了。

 

 

 

  1 #ifndef ONLINE_JUDGE
  2 #define __DEBUG__ 0
  3 #endif
  4 /*
  5 * =======================================
  6 *    FileName: code.cpp
  7 *        Desc: 
  8 *      Author: vinceliang
  9 *       Email: liangguoqiu@gmail.com
 10 *    HomePage: 
 11 *     Version: 0.0.1
 12 *  LastChange: 2014-07-15 12:16:49
 13 *     History:
 14 *========================================
 15 */
 16 #ifdef __DEBUG__
 17 #define Log(...) printf(__VA_ARGS__)
 18 #else
 19 #define Log(...) //
 20 #endif
 21 #include <algorithm>
 22 #include <string>
 23 #include <complex>
 24 #include <cassert>
 25 #include <memory>
 26 #include <set>
 27 #include <stack>
 28 #include <map>
 29 #include <list>
 30 #include <deque>
 31 #include <numeric>
 32 #include <cctype>
 33 #include <cstddef>
 34 #include <vector>
 35 #include <queue>
 36 #include <iostream>
 37 #include <iomanip>
 38 #include <iterator>
 39 #include <cmath>
 40 #include <cstdio>
 41 #include <cstdlib>
 42 #include <sstream>
 43 #include <fstream>
 44 #include <ctime>
 45 #include <cstring>
 46 #include <functional>
 47 #include <bitset>
 48 using namespace std;
 49 #if defined(_MSC_VER) || defined(__BORLANDC__)
 50 typedef unsigned __int64 uint64;
 51 typedef unsigned __int64 ULL;
 52 typedef signed __int64 int64;
 53 typedef signed __int64 LL;
 54 #else
 55 typedef unsigned long long uint64;
 56 typedef unsigned long long ULL;
 57 typedef signed long long int64;
 58 typedef signed long long LL;
 59 #endif
 60 typedef vector<int> VI;
 61 typedef vector<string> VS;
 62 typedef pair<int, int> PII;
 63 typedef pair<int64, int64> PLL;
 64 typedef vector<int64> VL;
 65 #define pb push_back
 66 #define pob pop_back
 67 #define mp make_pair
 68 #define fi first
 69 #define se second
 70 #define PII pair< int,int >
 71 #define PSS pair< string,string >
 72 #define PDD pair< double,double >
 73 #define PLL pair< LL, LL >
 74 #define FOR( i, a, b ) for ( int i=(a), _n=(b); i < _n; ++i )
 75 #define FORE( i, a, b ) for ( int i=(a), _n=(b); i <= _n; ++i )
 76 #define FORD( i, a, b ) for ( int i=(a), _n=(b); i >= _n; --i )
 77 #define REP( i, n ) FOR( i, 0, (n) )
 78 #define REPE( i, n ) FORE( i, 1, (n) )
 79 #define ALL( c ) (c).begin(), (c).end()
 80 #define SORT( c ) sort( ALL( c ) )
 81 #define LEN( s ) (int)( (s).size() )
 82 #define CLS( a ) memset( (a),0,sizeof(a) )
 83 #define IOS ios::sync_with_stdio( false ) 
 84 const double PI = 3.1415926535897932384626433832795028841971;
 85 const double EPS = 1E-9;
 86 const int64 INF64 = (int64)1E18;
 87 const int INF = 1 << 30;
 88 const int maxn = 1000005;
 89 
 90 int eh[maxn], tot;
 91 LL dist[maxn];
 92 LL dist2[maxn];
 93 bool vist[maxn];
 94 int n, m, k;
 95 
 96 struct Edge {
 97     int u, v;
 98     LL cost;
 99     int next;
100     Edge() {};
101     Edge( int a, LL b ) { v = a, cost = b; }
102     Edge( int a, int b, LL c, int d ) : u(a), v(b), cost(c), next(d) {}
103     bool operator < ( const Edge &x ) const {
104         return cost > x.cost;
105     }
106 };
107 
108 Edge edge[maxn];
109 int pre[maxn];
110 
111 int Dijk( int s )
112 {
113     for ( int i = 1; i <= n; ++i ) 
114     {
115         vist[i] = false, dist[i] = INF64;
116         pre[i] = 1;
117     }
118     dist[s] = 0;
119     priority_queue< Edge > que;
120     que.push( Edge( s, 0 ) );
121     int ans = 0;
122     while ( !que.empty() )
123     {
124         Edge tmp = que.top();
125         que.pop();
126         int u = tmp.v, cost = tmp.cost;
127         if ( vist[u] ) continue;
128         ans += cost, vist[u] = true;
129         for (  int i = eh[u]; i != -1; i = edge[i].next )
130         {
131             int v = edge[i].v;
132             if ( !vist[v] && ( dist[v] > dist[u] + edge[i].cost || (pre[v] == s && dist[v] == dist[u] + edge[i].cost) ) )
133             {
134                 dist[v] = dist[u] + edge[i].cost;
135                 pre[v] = u;
136                 que.push( Edge( v, dist[v] ) );
137             }
138         }
139 
140     }
141     return ans;
142 }
143 
144 void addedge( int a, int b, LL c )
145 {
146     Edge e = Edge( a, b, c, eh[a] );
147     edge[tot] = e;
148     eh[a] = tot++;
149 }
150 
151 void init()
152 {
153     tot = 0;
154     memset( eh, -1, sizeof( eh ) );
155 }
156 
157 int point[maxn];
158 LL value[maxn];
159 int pcnt;
160 
161 int Point1[maxn];
162 int Point2[maxn];
163 LL Value[maxn];
164 LL MinVal[maxn];
165 bool hascheck[maxn];
166 
167 void run()
168 {
169     //IOS;
170     while( cin >> n >> m >> k ) 
171     {
172         pcnt = 1;
173         init();
174         for ( int i = 1; i <= m; ++i )
175         {
176             int u, v;
177             LL w;
178             cin >> u >> v >> w;
179             addedge( u, v, w );
180             addedge( v, u, w );
181             Point1[i] = u;
182             Point2[i] = v;
183             Value[i] = w;
184         }
185 
186         Dijk( 1 );
187 
188         for ( int i = 1; i <= n; ++i )
189         {
190             MinVal[i] = -1;
191             hascheck[i] = 0;
192             dist2[i] = dist[i];
193         }
194 
195         init();
196 
197         for ( int i = 1; i <= m; ++i )
198         {
199             addedge( Point1[i], Point2[i], Value[i] );
200             addedge( Point2[i], Point1[i], Value[i] );
201         }
202 
203         for ( int i = 1; i <= k; ++i )
204         {
205             int s;
206             LL x;
207             cin >> s >> x;
208             if ( MinVal[s] == -1 )
209                 MinVal[s] = x;
210             else if ( MinVal[s] > x )
211                 MinVal[s] = x;
212 
213             point[pcnt] = s;
214             value[pcnt] = x;
215             pcnt++;
216 
217             addedge( 1, s, x );
218             addedge( s, 1, x );
219 
220 
221         }
222 
223         Dijk( 1 );
224 
225         int cnt = 0;
226 
227         for ( int i = 1; i <= k; ++i )
228         {
229             int s;
230             LL x;
231             s = point[i];
232             x = value[i];
233 
234             if ( MinVal[s] != x || hascheck[s] == 1 )
235             {
236                 cnt++;
237                 continue;
238             }
239 
240             if ( dist2[s] <= x )
241                 cnt++;
242             else if ( dist[s] != x )
243                 cnt++;
244             else if ( pre[s] != 1 )
245                 cnt++;
246 
247 
248             hascheck[s] = 1;
249         }
250 
251         cout << cnt << endl;
252     }
253 }
254 
255 int main( int argc, char **argv )
256 {
257 
258 #ifndef ONLINE_JUDGE
259        freopen("in.txt", "r", stdin);
260 //      freopen("out.txt", "w", stdout);
261 #endif
262        time_t st = clock();
263        run();
264        Log("\n=============\n");
265        Log("Time: %.2lf sec\n", (clock() - st) / double(CLOCKS_PER_SEC));
266        return 0;
267 }
View Code

 

posted @ 2014-09-24 18:20  vinceliang  阅读(215)  评论(0)    收藏  举报