Luogu P1073 最优贸易
感觉是一道很友善的蓝题 图论都很友善qwq
一开始看题,以为可以多次买卖,一想,惨了,DP:-(
然后在扫了一遍发现原来只进行最多一次买卖
那贪心吧,该怎么贪。。。
就是找水晶球最贵最便宜城市吧,但不一定联通啊。。。
难道排序之后按大到小枚举卖的城市,按小到大枚举买的城市?然后问一下可不可以跑得到???这样子吗。。。可以实现吗 肯定不可以啊
于是又膜了题解
很妙啊原来也不难
看了思路觉得特别友善啊 颇为开心的就开始打了
好像之前的题都比这个难啊quq果然还是我太弱了
昨天打了一个中午,60.。。
今天终于查出错了然后A了
大概思路
跑两次spfa一次从头开始,
一次从尾开始,记录最小值和最大值,
第二次跑的时候不断问每一个点最大值和最小值的差,
最大的差就是answer!:建边时要建反向边,分开两张图跑
对于每个点的最小值:是从起点跑到这所经过的城市中水晶球最低的价格
最大值:是从终点跑到这所经过的城市中水晶球最高的价格
#include<cstdio>
#include<cstring>
int n,m,len,lenn;
int ans=0,first[100100],ffirst[100100];
int a[100100],v[100100],f[100100],sum1[100010],sum2[100010];
struct nod1{int x,y,next;}b[1000010],c[1000010];
int minn(int x,int y)
{
return x<y?x:y;
}
int maxx(int x,int y)
{
return x>y?x:y;
}
int ins(int x,int y)
{
len++;
b[len].x=x;
b[len].y=y;
b[len].next=first[x];
first[x]=len;
}
int iins(int x,int y)
{
lenn++;
c[lenn].x=x;
c[lenn].y=y;
c[lenn].next=ffirst[x];
ffirst[x]=lenn;
}
int spfa1()
{
int st=1,ed=2;
f[st]=1;
sum1[1]=a[1];
v[1]=1;
while(st!=ed)
{
int x=f[st];
for(int i=first[x];i;i=b[i].next)
{
int y=b[i].y;
if(sum1[y]>sum1[x]||sum1[y]>a[y])
{
sum1[y]=minn(a[y],sum1[x]);
if(v[y]==0)
{
v[y]=1;
f[ed]=y;
ed++;
}
}
}
st++;
v[x]=0;
}
}
int spfa2()
{
int st=1,ed=2;
memset(f,0,sizeof(0));
memset(v,0,sizeof(v));
f[st]=n;
sum2[n]=a[n];
v[n]=1;
ans=maxx(ans,sum2[n]-sum1[n]);
while(st!=ed)
{
int x=f[st];
for(int i=ffirst[x];i;i=c[i].next)
{
int y=c[i].y;
if(sum2[y]<sum2[x]||sum2[y]<a[y])
{
sum2[y]=maxx(sum2[x],a[y]);
ans=maxx(ans,sum2[y]-sum1[y]);
if(v[y]==0)
{
v[y]=1;
f[ed]=y;
ed++;
}
}
}
st++;
v[x]=0;
}
}
int main()
{
//freopen("aa.in","r",stdin);
memset(sum1,63,sizeof(sum1));
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);sum1[i]=99999999;
}
for(int i=1;i<=m;i++)
{
int x,y,z;
scanf("%d %d %d",&x,&y,&z);
if(z==1)
{
ins(x,y);
iins(y,x);
}
if(z==2)
{
ins(x,y);ins(y,x);
iins(x,y);iins(y,x);
}
}
spfa1();
spfa2();
printf("%d",ans);
}
思维力还是不够啊。。。
这个也是翻了题解的(好像什么题都翻了)。。。
自己想的总是又被自己推翻,还是太菜了。。