标签:style blog io color os sp for on div
题意:
给一个无向图,总共有 n个点,m+k条边,给定点所连的k条边可以选择删除
问最多删除多少条可以保持该定点到其他点的最短路不变
题解:
从定点出发做单元最短路
首先如果定点到某个点的最短路小于 可删边的长度,则肯定可以删除
此外如果最短路与可删边长度相等,而且最短路条数大于1,肯定也可以删除
所以在做最短路的时候需要记录一下条数
//同时还会有重边,也要注意处理
ps...这题sxbk的把普通的spfa 都卡了。。加了slf优化才过,据说dij可以轻松过。。不过我没试2333
以后写spfa还是都写deque版的吧= =!
代码:
#include <stdio.h> #include <cstring> #include <iostream> #include <algorithm> #include <queue> using namespace std; const int inf =1000000001; struct edge { int from,to,w,next; }e[800010]; int head[100010]; int vis[100010]; int dist[100010]; int vi[100010]; int hs[100010]; int n,m,t; void add(int i,int j,int w) { e[t].from=i; e[t].to=j; e[t].w=w; e[t].next=head[i]; head[i]=t++; return ; } void spfa(int s) { deque <int> q; for(int i=1;i<=n;i++) dist[i]=inf; memset(vis,false,sizeof(vis)); q.push_back(s); dist[s]=0; while(!q.empty()) { int u=q.front(); q.pop_front(); vis[u]=false; for(int i=head[u];i!=-1;i=e[i].next) { int v=e[i].to; if(dist[v]>=dist[u]+e[i].w) { dist[v]=dist[u]+e[i].w; if(dist[v]==hs[v]) vi[v]++; else if(dist[v]<hs[v]) vi[v]=2; if(!vis[v]) { vis[v]=true; if(!q.empty()&&dist[v]<dist[q.front()]) //spfa的slf优化 q.push_front(v); else q.push_back(v); } } } } } int main() { int a,b,c,k; scanf("%d%d%d",&n,&m,&k); t=0; memset(head,-1,sizeof(head)); while(m--) { scanf("%d%d%d",&a,&b,&c); add(a,b,c); add(b,a,c); } int ans=0; while(k--) { scanf("%d%d",&b,&c); if(hs[b]==0) { hs[b]=c; add(1,b,c); add(b,1,c); } else //处理重边 { ans++; if(c<hs[b]) { hs[b]=c; add(1,b,c); add(b,1,c); } } } spfa(1); for(int i=2;i<=n;i++) { if(vi[i]>1) ans++; } printf("%d\n",ans); return 0; }
标签:style blog io color os sp for on div
原文地址:http://www.cnblogs.com/oneshot/p/4121971.html