您的位置:首页 > 编程语言 > C语言/C++

CodeForces 449 B. Jzzhu and Cities

2014-09-24 17:52 881 查看
传送门:Jzzhu and Cities

B. Jzzhu and Cities

time limit per test
2 seconds

memory limit per test
256 megabytes

input
standard input

output
standard output

Jzzhu is the president of country A. There are n cities numbered from 1 to n in
his country. City 1 is the capital of A. Also there are mroads
connecting the cities. One can go from city ui to vi (and
vise versa) using the i-th road, the length of this road is xi.
Finally, there are k train routes in the country. One can use the i-th
train route to go from capital of the country to city si (and
vise versa), the length of this route is yi.

Jzzhu doesn't want to waste the money of the country, so he is going to close some of the train routes. Please tell Jzzhu the maximum number of the train routes which can be closed under the following condition: the length of the shortest path from every city
to the capital mustn't change.

Input

The first line contains three integers n, m, k (2 ≤ n ≤ 105; 1 ≤ m ≤ 3·105; 1 ≤ k ≤ 105).

Each of the next m lines contains three integers ui, vi, xi (1 ≤ ui, vi ≤ n; ui ≠ vi; 1 ≤ xi ≤ 109).

Each of the next k lines contains two integers si and yi (2 ≤ si ≤ n; 1 ≤ yi ≤ 109).

It is guaranteed that there is at least one way from every city to the capital. Note, that there can be multiple roads between two cities. Also, there can be multiple routes going to the same city from the capital.

Output

Output a single integer representing the maximum number of the train routes which can be closed.

Sample test(s)

input
5 5 3
1 2 1
2 3 2
1 3 3
3 4 4
1 5 5
3 5
4 5
5 5


output
2


input
2 2 3
1 2 22 1 3
2 1
2 22 3


output
2


题意:

题意一定要看仔细,这里说一个国家,有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这条路,那么就又少一条铁路了。

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

#ifndef ONLINE_JUDGE
#define __DEBUG__ 0
#endif
/*
* =======================================
* FileName: code.cpp
* Desc:
* Author: vinceliang
* Email: liangguoqiu@gmail.com
* HomePage:
* Version: 0.0.1
* LastChange: 2014-07-15 12:16:49
* History:
*========================================
*/
#ifdef __DEBUG__
#define Log(...) printf(__VA_ARGS__)
#else
#define Log(...) //
#endif
#include <algorithm>
#include <string>
#include <complex>
#include <cassert>
#include <memory>
#include <set>
#include <stack>
#include <map>
#include <list>
#include <deque>
#include <numeric>
#include <cctype>
#include <cstddef>
#include <vector>
#include <queue>
#include <iostream>
#include <iomanip>
#include <iterator>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <sstream>
#include <fstream>
#include <ctime>
#include <cstring>
#include <functional>
#include <bitset>
using namespace std;
#if defined(_MSC_VER) || defined(__BORLANDC__)
typedef unsigned __int64 uint64;
typedef unsigned __int64 ULL;
typedef signed __int64 int64;
typedef signed __int64 LL;
#else
typedef unsigned long long uint64;
typedef unsigned long long ULL;
typedef signed long long int64;
typedef signed long long LL;
#endif
typedef vector<int> VI;
typedef vector<string> VS;
typedef pair<int, int> PII;
typedef pair<int64, int64> PLL;
typedef vector<int64> VL;
#define pb push_back
#define pob pop_back
#define mp make_pair
#define fi first
#define se second
#define PII pair< int,int >
#define PSS pair< string,string >
#define PDD pair< double,double >
#define PLL pair< LL, LL >
#define FOR( i, a, b ) for ( int i=(a), _n=(b); i < _n; ++i )
#define FORE( i, a, b ) for ( int i=(a), _n=(b); i <= _n; ++i )
#define FORD( i, a, b ) for ( int i=(a), _n=(b); i >= _n; --i )
#define REP( i, n ) FOR( i, 0, (n) )
#define REPE( i, n ) FORE( i, 1, (n) )
#define ALL( c ) (c).begin(), (c).end()
#define SORT( c ) sort( ALL( c ) )
#define LEN( s ) (int)( (s).size() )
#define CLS( a ) memset( (a),0,sizeof(a) )
#define IOS ios::sync_with_stdio( false )
const double PI = 3.1415926535897932384626433832795028841971;
const double EPS = 1E-9;
const int64 INF64 = (int64)1E18;
const int INF = 1 << 30;
const int maxn = 1000005;

int eh[maxn], tot;
LL dist[maxn];
LL dist2[maxn];
bool vist[maxn];
int n, m, k;

struct Edge {
int u, v;
LL cost;
int next;
Edge() {};
Edge( int a, LL b ) { v = a, cost = b; }
Edge( int a, int b, LL c, int d ) : u(a), v(b), cost(c), next(d) {}
bool operator < ( const Edge &x ) const {
return cost > x.cost;
}
};

Edge edge[maxn];
int pre[maxn];

int Dijk( int s )
{
for ( int i = 1; i <= n; ++i )
{
vist[i] = false, dist[i] = INF64;
pre[i] = 1;
}
dist[s] = 0;
priority_queue< Edge > que;
que.push( Edge( s, 0 ) );
int ans = 0;
while ( !que.empty() )
{
Edge tmp = que.top();
que.pop();
int u = tmp.v, cost = tmp.cost;
if ( vist[u] ) continue;
ans += cost, vist[u] = true;
for ( int i = eh[u]; i != -1; i = edge[i].next )
{
int v = edge[i].v;
if ( !vist[v] && ( dist[v] > dist[u] + edge[i].cost || (pre[v] == s && dist[v] == dist[u] + edge[i].cost) ) )
{
dist[v] = dist[u] + edge[i].cost;
pre[v] = u;
que.push( Edge( v, dist[v] ) );
}
}

}
return ans;
}

void addedge( int a, int b, LL c )
{
Edge e = Edge( a, b, c, eh[a] );
edge[tot] = e;
eh[a] = tot++;
}

void init()
{
tot = 0;
memset( eh, -1, sizeof( eh ) );
}

int point[maxn];
LL value[maxn];
int pcnt;

int Point1[maxn];
int Point2[maxn];
LL Value[maxn];
LL MinVal[maxn];
bool hascheck[maxn];

void run()
{
//IOS;
while( cin >> n >> m >> k )
{
pcnt = 1;
init();
for ( int i = 1; i <= m; ++i )
{
int u, v;
LL w;
cin >> u >> v >> w;
addedge( u, v, w );
addedge( v, u, w );
Point1[i] = u;
Point2[i] = v;
Value[i] = w;
}

Dijk( 1 );

for ( int i = 1; i <= n; ++i )
{
MinVal[i] = -1;
hascheck[i] = 0;
dist2[i] = dist[i];
}

init();

for ( int i = 1; i <= m; ++i )
{
if ( Point1[0] == 89457 )
{
if ( Point1[i] == 1 || Point2[i] == 1 || Value[i] == 0 )
{
cout << Point1[i] << " " << Point2[i] << " " << Value[i] << endl;
}
}
addedge( Point1[i], Point2[i], Value[i] );
addedge( Point2[i], Point1[i], Value[i] );
}

for ( int i = 1; i <= k; ++i )
{
int s;
LL x;
cin >> s >> x;
if ( MinVal[s] == -1 )
MinVal[s] = x;
else if ( MinVal[s] > x )
MinVal[s] = x;

//if ( n == 100000 )
// cout << s << " " << x << endl;
point[pcnt] = s;
value[pcnt] = x;
pcnt++;

addedge( 1, s, x );
addedge( s, 1, x );

if ( x == 0 )
cout << s << " " << x << endl;

}

Dijk( 1 );

int cnt = 0;

for ( int i = 1; i <= k; ++i )
{
int s;
LL x;
s = point[i];
x = value[i];

if ( MinVal[s] != x || hascheck[s] == 1 )
{
cnt++;
continue;
}

if ( dist2[s] <= x )
cnt++;
else if ( dist[s] != x )
cnt++;
else if ( pre[s] != 1 )
cnt++;

hascheck[s] = 1;
}

cout << cnt << endl;
}
}

int main( int argc, char **argv )
{

#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
#endif
time_t st = clock();
run();
Log("\n=============\n");
Log("Time: %.2lf sec\n", (clock() - st) / double(CLOCKS_PER_SEC));
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ACM codeforces C++ graphy dijk