Time Limit:10000MS Memory Limit:65536K
Total Submit:28 Accepted:25
Case Time Limit:1000MS
Description
Input
Output
解题思路
这一道题想了挺久的 然鹅还是没有想出正解 。
其实就是分为了两个spfa:
1先只算出从1出发一直到n的进价(最小值)。
2再把道路的走向全部反过来,算出从n出发一直到1的卖价(最大值)。
最后再枚举1~n算出最大的得益。
#include<iostream>
#include<cstring>
#include<iomanip>
#include<cmath>
#include<cstdio>
using namespace std;
const int INF=10000000;
int n,m,k,h=0,t=1,v[100000],dis[100000][3],q[100000],head[100000],head2[100000],minn=INF,maxn,ans=0,bsy[100000];//dis[i][1]记录第一次spfa的最短路
struct c{
int x,next;
}a[1000000];
struct c1{
int x,next;
}b[1000000];
void spfa(){//第一个spfa求最小值
memset(v,0,sizeof(v));
for(int i=1;i<=n;i++)
dis[i][1]=0x7fffffff;
dis[1][1]=bsy[1];
v[1]=1;
q[1]=1;
while(h<t)
{
h++;
for(int i=head[q[h]];i;i=a[i].next)
{
if(min(bsy[a[i].x],dis[q[h]][1])<dis[a[i].x][1])
{
dis[a[i].x][1]=min(bsy[a[i].x],dis[q[h]][1]);
if(!v[a[i].x])
{
t++;
v[a[i].x]=1;
q[t]=a[i].x;
}
}
}
v[q[h]]=0;
}
}
void spfa2(){//第二个spfa求最大值
memset(v,0,sizeof(v));
memset(q,0,sizeof(q));
dis[1][2]=bsy[n];
v[n]=1;
q[1]=n;
h=0,t=1;
while(h<t)
{
h++;
for(int i=head2[q[h]];i;i=b[i].next)
{
if(max(bsy[b[i].x],dis[q[h]][2])>dis[b[i].x][2])
{
dis[b[i].x][2]=max(bsy[b[i].x],dis[q[h]][2]);
if(!v[b[i].x])
{
t++;
v[b[i].x]=1;
q[t]=b[i].x;
}
}
}
v[q[h]]=0;
}
}
void add(int x,int y){ //顺行的邻接表
++k;
a[k].x=y;
a[k].next=head[x];
head[x]=k;
}
void add2(int x,int y){ //逆行的邻接表
++k;
b[k].x=y;
b[k].next=head2[x];
head2[x]=k;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&bsy[i]);
for(int i=1;i<=m;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add(x,y);
add2(y,x);
if(z==2)//双向的话要再反过来执行一次
{
add(y,x);
add2(x,y);
}
}
spfa();
spfa2();
for(int i=2;i<n;i++)
if((dis[i][2]-dis[i][1])>ans)
ans=dis[i][2]-dis[i][1];
cout<<ans;
}