NYOJ 307
View Code
1 /* 2 题外话: 3 没想到这是一道最短路题 4 原来最短路可以这样变形,有时也可以多次利用最短路 5 求一个问题 6 思路: 7 我们从每个有藏宝的地方为起点 求到各个点的可以的最大 8 重量 9 10 我们相当于求出了从出口 到 一个藏宝点 所 11 允许的最大重量 12 13 把所有藏宝点的按重量 排序(从小到大) 14 先到最小的藏宝点带上 宝物 再去次大 15 一次类推 16 */ 17 #include<iostream> 18 #include<cstdio> 19 #include<cstring> 20 #include<algorithm> 21 using namespace std; 22 23 const int size = 8001; 24 struct node 25 { 26 int e; 27 int v; 28 int next; 29 }edge[30001]; 30 int k[size]; 31 int en=0; 32 33 int qmin(int x,int y) 34 { 35 if(x<y)return x; 36 else return y; 37 } 38 39 int dij(int beg,int last,int N) 40 { 41 int i; 42 bool flag[size]; 43 int d[size]; 44 memset(flag,0,sizeof(flag)); 45 memset(d,0,sizeof(d)); 46 d[beg]=7777777; 47 flag[beg]=1; 48 while(beg!=last) 49 { 50 for(i=k[beg];i!=-1;i=edge[i].next) 51 { 52 int e = edge[i].e; 53 int v = edge[i].v; 54 if(!flag[e] && d[e]<qmin(d[beg],v)) 55 d[e]=qmin(d[beg],v); 56 } 57 int tmax=0; 58 for(i=1;i<=N;++i) 59 if(!flag[i]&&d[i]>tmax) 60 { 61 tmax=d[i]; 62 beg=i; 63 } 64 flag[beg]=1; 65 } 66 return d[last]; 67 } 68 69 int main() 70 { 71 int N,M,K,W,i; 72 int x,y,z; 73 int kc[size]; 74 int d[size]; 75 while(~scanf("%d%d%d%d",&N,&M,&K,&W)) 76 { 77 memset(k,-1,sizeof(k)); 78 en=0; 79 for(i=1;i<=K;++i) 80 scanf("%d",&kc[i]); 81 for(i=0;i<M;++i) 82 { 83 scanf("%d%d%d",&x,&y,&z); 84 85 edge[en].e=y; 86 edge[en].v=z; 87 edge[en].next=k[x]; 88 k[x]=en++; 89 90 edge[en].e=x; 91 edge[en].v=z; 92 edge[en].next=k[y]; 93 k[y]=en++; 94 } 95 for(i=1;i<=K;++i) 96 d[i]=dij(kc[i],1,N); 97 sort(d+1,d+K+1); 98 int total=0; 99 for(i=1;i<=K;++i) 100 if(d[i]>=(total+1)*W) 101 total++; 102 printf("%d\n",total); 103 } 104 return 0; 105 }