您的位置:首页 > 其它

Codeforces 449 B. Jzzhu and Cities(图论dijk)

2017-01-19 15:18 357 查看
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 m roads connecting the cities. One can go from city u i to v i (and vise versa) using the i -th road, the length of this road is x i . 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 s i (and vise versa), the length of this route is y i .

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 ≤ 10 5 ; 1 ≤ m ≤ 3·10 5 ; 1 ≤ k ≤ 10 5 ) .

Each of the next m lines contains three integers u i , v i , x i (1 ≤ u i , v i ≤ n ; u i ≠ v i ; 1 ≤ x i ≤ 10 9 ) .

Each of the next k lines contains two integers s i and y i (2 ≤ s i ≤ n ; 1 ≤ y i ≤ 10 9 ) .

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.

题意:

有n个城市 从1到n,其中1为首都。每个城市之间有很多条道路,1到其他城市之间有一些铁轨。现在要在最短路不变的情况下,删掉尽量多的铁轨。输出删掉的铁轨数。

真·从早wa到晚,最后换了一种写法= =。。。就很难过

一开始的想法是把所有边都加进去,然后dijk,但在更新dis值得时候多增加一个数组rout[u]记录当前这个点的最短路径上有多少条铁轨。

如果dis[son]>dis[father]+eg[i].w 那么就根据i是不是铁轨更新这个rout

如果dis[son]==dis[father]+eg[i].w 那么就从看是原先rout[son]小还是通过边i 从father转移过来更小,依此来更新rout[son],

同时每次更新都要记录这个点的最短路是由哪个边转移过来的。

最后统计所有点所记录的边,如果是铁轨边那么就tot++;

tot是保留下来的铁轨数

ans就是k-tot;

自我感觉好像没得毛病哈。。。。。

测一些小数据基本都能过,但一旦大了 ans就会偏小。。。。

现在都还没想通。。。

代码贴出来有大佬愿意看的话麻烦告诉我猫饼在哪儿QAQ

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <queue>
#include <set>
using namespace std;
struct Pair{
int D,V;
Pair(long long d,int v){
D=d,V=v;
}
friend bool operator< (const Pair a,const Pair b){
return a.D>b.D;
}
};
struct typ{
int to,fl,nxt;
long long w;
}edge[800005];
int tot,n,m,k;
int used[100005],path[100005],rout[100005],head[100005];
long long dis[100005];
void dijk(){
memset(used,0,sizeof used);
for(int i=0;i<=n;i++) dis[i]=1e15;
//  cout<<dis[1]<<endl;
for(int i=0;i<=n;i++) rout[i]=1e9+5;
//  cout<<rout[1]<<endl;
priority_queue<Pair>que;
dis[1]=0;rout[1]=0;
que.push(Pair(0,1));
int tot=0;
while(!que.empty()){
Pair now=que.top();
que.pop();
if(used[now.V]) continue;
tot++;
used[now.V]=1;
for(int i=head[now.V];i!=-1;i=edge[i].nxt){
int to=edge[i].to;
if(dis[to]>dis[now.V]+edge[i].w){
//  if(to==5) cout<<dis[to]<<' '<<dis[now.V]+edge[i].w<<"****"<<endl;
dis[to]=dis[now.V]+edge[i].w;
rout[to]=rout[now.V];
path[to]=i;
if(edge[i].fl){
rout[to]++;
}
que.push(Pair(dis[to],to));
}else if(dis[to]==dis[now.V]+edge[i].w){
if(edge[i].fl && rout[now.V]+1<rout[to]){
rout[to]=rout[now.V]+1;
path[to]=i;
}
if(edge[i].fl==0 && rout[now.V]<rout[to]){
rout[to]=rout[now.V];
path[to]=i;
//  if(to==5) cout<<now.V<<' '<<i<<endl;

}
}
}
if(tot==n-1) break;
}
//  for(int i=1;i<=n;i++) cout<<path[i]<<' ';
}
void addedge(int u,int v,long long c,int fl){
edge[tot].to=v;
edge[tot].w=c;
edge[tot].fl=fl;
edge[tot].nxt=head[u];
head[u]=tot;
tot++;
}
int main(){
//freopen("in.txt","r",stdin);
cin>>n>>m>>k;
tot=0;
memset(head,-1,sizeof head);
int x,y;
long long z;
for(int i=1;i<=m;i++){
scanf("%d%d%lld",&x,&y,&z);
addedge(x,y,z,0);
addedge(y,x,z,0);
}
for(int i=1;i<=k;i++){
scanf("%d%d",&x,&y);
addedge(1,x,y,1);
addedge(x,1,y,1);
}
dijk();
set<int>st;
st.clear();
for(int i=2;i<=n;i++){
if(edge[path[i]].fl==1){
st.insert(path[i]);
//  cout<<path[i]<<' '<<edge[path[i]].w<<endl;
}
}
cout<<k-st.size()<<endl;
return 0;
}


后面换了种写法,还是全部加进去,然后dijk

增加一个记录入度的边。

最后扫一遍k个铁轨,判断一下

如果这个铁轨长度大于最短路 那么说明这个铁轨肯定要删去 ans++

如果等于 并且这个点入度不为1 那么说明可以删去 ans++,in[u]–;

最后输出答案。

这种思路要简单清晰很多。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <queue>
#include <set>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
struct Pair{
int D,V;
Pair(long long  d,int v){
D=d,V=v;
}
friend bool operator< (const Pair a,const Pair b){
return a.D>b.D;
}
};
struct typ{
int to,fl,nxt;
long long w;
}edge[800005];
int tot,n,m,k,ans;
int used[100005],head[100005],rout[100005],in[100005],dest[100005];
long long dis[100005];
void dijk(){
memset(used,0,sizeof used);
priority_queue<Pair>que;
dis[1]=0;
que.push(Pair(0,1));
while(!que.empty()){
Pair now=que.top();
que.pop();
//  cout<<now.V<<endl;
if(used[now.V]) continue;
used[now.V]=1;
for(int i=head[now.V];i!=-1;i=edge[i].nxt){
int to=edge[i].to;
if(dis[to]==dis[now.V]+edge[i].w){
in[to]++;
}
if(dis[to]>dis[now.V]+edge[i].w){
//  if(to==5) cout<<dis[to]<<' '<<dis[now.V]+edge[i].w<<"****"<<endl;
in[to]=1;
dis[to]=dis[now.V]+edge[i].w;
que.push(Pair(dis[to],to));
}
}
}
//  for(int i=1;i<=n;i++) cout<<dis[i]<<' ';
}
void addedge(int u,int v,long long c){
edge[tot].to=v;
edge[tot].w=c;
edge[tot].nxt=head[u];
head[u]=tot;
tot++;
}
long long Min(long long a,long long b){
if(a>b) return b;
return a;
}
int main(){
freopen("in.txt","r",stdin);
IOS;
cin>>n>>m>>k;
tot=0;
memset(head,-1,sizeof head);
memset(in,0,sizeof in);
int x,y;
long long z;
for(int i=1;i<=m;i++){
cin>>x>>y>>z;
addedge(x,y,z);
addedge(y,x,z);
}
for(int i=0;i<=n;i++) dis[i]=1e15;
ans=0;
for(int i=1;i<=k;i++){
cin>>x>>z;
addedge(1,x,z);
dest[i]=x;
rout[i]=z;
//cout<<dis[x]<<endl;
}
dijk();
int ans=0;
for(int i=1;i<=k;i++){
int u=dest[i];
if(dis[u]==rout[i]&& in[u]>1) {
ans++;
in[u]--;
}else if(dis[u]<rout[i]){
ans++;
}

}
cout<<ans<<endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  codeforces