题目传送门
解题思路:
先吐槽一下,因为本人太弱,狂肝4.5小时才A掉.要是在考场上不就废了
本题拿过来,很明显的贪心思路就是在每条1到n的路径上找最大和最小值,然后做差维护答案.
然而这样是不对,因为有可能对于一条路径,最小值在最大值后面出现,而这样这条路径上的答案明显不是它们的差值.
怎么办呢? 答案就是我们可以对于每个点,注意是每个"点",找1到这个点路径上的最小值,这个点到n的最大值,作差,这样至少对于这个点来说是最优解.
然后对于所有在1到n路径上的点的差维护最大值即可.
还有一个问题,我们怎样知道哪些点能从1到这个点然后再走到n呢?
当然从1走到当前点好办,直接遍历即可.那n呢,怎么办?其实只要反过来一想,把n想象成1,倒着便利一遍这个图就行.
所以,综上所述,只要正着跑一遍SPFA,反着跑一遍SPFA,然后维护答案即可.
注意:
1.因为要跑两遍SPFA,所以我们要正着,反着存两遍图
2.正着的SPFA是求最小值,而反着的SPFA是求最大值.
AC代码:
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<queue> 5 #include<algorithm> 6 #include<limits.h> 7 8 using namespace std; 9 10 queue<int > l1,l2; 11 int a1,bn,n,m,a[100001],head[100001],tot,head1[100001],_tot,dist[100001],b[100001],dist1[100001]; 12 bool p[100001]; 13 struct kkk { 14 int next,to,v; 15 }e[500001],e1[500001]; 16 17 inline void add(int x,int y) { 18 e[++tot].to = y; 19 e[tot].next = head[x]; 20 e[tot].v = a[y]; 21 head[x] = tot; 22 } 23 24 inline void add1(int x,int y) { 25 e1[++_tot].to = y; 26 e1[_tot].next = head1[x]; 27 e1[tot].v = b[y]; 28 head1[x] = _tot; 29 } 30 31 inline void spfa_first_time(int s) { 32 memset(dist,0x3f,sizeof(dist)); 33 memset(p,0,sizeof(p)); 34 dist[s] = a[s]; 35 l1.push(s); 36 p[s] = true; 37 while(!l1.empty()) { 38 int u = l1.front(); 39 l1.pop(); 40 p[u] = false; 41 for(int i = head[u];i != -1; i = e[i].next) { 42 int end = e[i].to; 43 int len = e[i].v; 44 if(dist[u] < dist[end] || len < dist[end]) { 45 dist[end] = min(dist[u],len); 46 if(!p[end]) { 47 l1.push(end); 48 p[end] = 1; 49 } 50 } 51 } 52 } 53 } 54 55 inline void spfa_last_time(int s) { 56 memset(dist1,0x80,sizeof(dist1)); 57 memset(p,0,sizeof(p)); 58 dist1[s] = b[s]; 59 l2.push(s); 60 p[s] = true; 61 while(!l2.empty()) { 62 int u = l2.front(); 63 l2.pop(); 64 p[u] = false; 65 for(int i = head1[u];i != -1; i = e1[i].next) { 66 int end = e1[i].to; 67 int len = e1[i].v; 68 if(dist1[u] > dist1[end] || len > dist1[end]) { 69 dist1[end] = max(dist1[u],len); 70 if(!p[end]) { 71 l2.push(end); 72 p[end] = 1; 73 }} 74 } 75 } 76 } 77 78 bool cmp(int q,int r) { 79 return q > r; 80 } 81 82 int main() { 83 memset(head,-1,sizeof(head)); 84 memset(head1,-1,sizeof(head1)); 85 scanf("%d%d",&n,&m); 86 for(int i = 1;i <= n; i++) { 87 scanf("%d",&a[i]); 88 b[i] = a[i]; 89 } 90 for(int i = 1;i <= m; i++) { 91 int x,y,z; 92 scanf("%d%d%d",&x,&y,&z); 93 if(z == 1) { 94 add(x,y); 95 add1(y,x); 96 } 97 if(z == 2) { 98 add(x,y); 99 add(y,x); 100 add1(x,y); 101 add1(y,x); 102 } 103 } 104 spfa_first_time(1);//正着 105 spfa_last_time(n);//反着 106 for(int i = 1;i <= n; i++) 107 a[i] = dist1[i] - dist[i]; 108 sort(a+1,a+1+n,cmp); 109 if(a[1] <= 0 || a[1] >= 0x3f3f3f3f) printf("0"); 110 else printf("%d",a[1]); 111 return 0; 112 }
//NOIP2009提高 T3