题意:
给你N个点,M条边的图,现在有L条铁路(铁路的起始点都为1)
问最多可以去掉多少条铁路使得点1到其他的点的最短距离不变
方法: 现将所有的边都加入到图中,其中是铁路的边做一个标记,用一个pre【】数组记录第i个点加入到集合当中的时候与i所连接的边
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
#define maxn 100005
#define maxm 300005
#define LL long long
int n, m, k, tot,ans;
//vis记录改点是否已经加入到集合当中去,head表示点i连接的边的表头,
//pre表示连接点i的是边pre[i],dis[i]表示点1到点i的最短距离
int vis[maxn], head[maxn], pre[maxn];
LL dis[maxn];
struct edge
{
int v, kind, next;
LL s;
}edge[7*maxm];
struct node
{
int idx;
LL d;
bool operator < (const node &fa) const
{
return d > fa.d;
}
};
priority_queue<node>q;
void add(int x,int y, LL L, int kind)
{
edge[tot].v= y;
edge[tot].s= L;
edge[tot].next= head[x];
edge[tot].kind= kind;
head[x]= tot++;
}
void dij()
{
node u;
u.d= 0, u.idx= 1;
q.push(u);
while(!q.empty())
{
while(vis[u.idx]&& !q.empty())
{
u= q.top();
q.pop();
}
if(vis[u.idx]) return;// 所有点都已加入到集合中
// printf("%d %d\n",u.idx, pre[u.idx]);
if(pre[u.idx]!= -1)
ans+= edge[pre[u.idx]].kind; //最短路连中接u.idx是边pre[u].idx没看懂
vis[u.idx]= 1;
dis[u.idx]= u.d;
//head[u.idx] 表示表头,edge[i].next=-1 表示表尾
for(int i= head[u.idx]; i!= -1; i= edge[i].next)
{
node v;
v.idx= edge[i].v;
v.d= u.d + edge[i].s;
//以新加入的点u.idx去更新未加入集合中点的最短路
if(dis[v.idx]== v.d && edge[i].kind!=1) //如果两条路距离相等,则步行的边优先
pre[v.idx]= i; //连接点v.idx是边pre[v.idx]= i;
if(dis[v.idx]==-1 || dis[v.idx]> v.d)
{
dis[v.idx]= v.d;
pre[v.idx]= i;
q.push(v);
}
}
}
}
int main()
{
while(scanf("%d %d %d",&n,&m,&k)!=EOF)
{
memset(vis, 0, sizeof(vis));
memset(head, -1, sizeof(head));
memset(pre, -1, sizeof(pre));
memset(dis, -1, sizeof(dis));
ans= tot= 0;
int x, y;
LL z;
for(int i= 1; i<= m; i++)
{
scanf("%d %d %lld", &x, &y, &z);
add(x, y, z, 0);
add(y, x, z, 0);
}
for(int i= 1; i<= k; i++)
{
scanf("%d %lld", &x, &z);
add(1, x, z, 1);
}
dij();
printf("%d\n",k-ans);
}
return 0;
}