#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=3e4+10;
const int INF=0x3f3f3f3f;
int n,m,hd[N],r[N],tot,nowrank,dis[N],lim[N],stack[N],tp,top,ans,minr[N];
struct Edge{
int v,w,nx;
}e[N*10];
struct Heap{
int x,w;
Heap(void){}
Heap(int _x,int _w):x(_x),w(_w){}
}heap[100*N];
void add(int u,int v,int w)
{
e[++tot].v=v;
e[tot].w=w;
e[tot].nx=hd[u];
hd[u]=tot;
}
bool cmp(const Heap&a,const Heap&b)
{
return a.w>b.w||(a.w==b.w&&r[a.x]<r[b.x]);
}
void dijk()
{
while(top)
{
Heap sta=heap[1];
pop_heap(heap+1,heap+top+1,cmp);
top--;
if(sta.w!=dis[sta.x])continue;
stack[++tp]=sta.x;
for(int i=hd[sta.x];i;i=e[i].nx)
{
if(r[e[i].v]>nowrank)continue;
if(dis[e[i].v]>sta.w+e[i].w&&lim[e[i].v]>sta.w+e[i].w)
{
dis[e[i].v]=sta.w+e[i].w;
heap[++top]=Heap(e[i].v,dis[e[i].v]);
push_heap(heap+1,heap+top+1,cmp);
}
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&r[i]);
for(int i=1,u,v,w;i<=m;i++)
scanf("%d%d%d",&u,&v,&w),add(u,v,w),add(v,u,w);
memset(dis,0x3f,sizeof(dis));
memset(lim,0x3f,sizeof(lim));
for(int i=10;i;i--)
{
nowrank=i;
memset(minr,0x3f,sizeof(minr));
for(int j=1;j<=n;j++)
if(r[j]==i)
{
heap[++top]=Heap(j,0);
dis[j]=0;
dijk();
for(;tp;tp--)
{
int k=stack[tp];
if(lim[k]>dis[k])ans++;
minr[k]=min(minr[k],dis[k]);
dis[k]=INF;
}
}
for(int j=1;j<=n;j++)
lim[j]=min(minr[j],lim[j]);
}
printf("%d\n",ans);
return 0;
}
总结
推结论的好题