Scarlet_Hypoc @ 2018-04-10 19:58:04
传说中的非正解: 我的思路是先逆向SPFA一遍,求出每一个点到n最少需要多少血量,然后再正向SPFA,求出是否能到每个节点,如果能,就判断是否可以更新从1到i最大花费的最小值,如果可以就更新,如果一样,判断从x走过来是否可以剩下更多血量,可以就更新,代码如下
#include <cstdio>
#include <cstring>
#define ll long long
int n,m,k,len=0;
struct node{int x,y,z,next;};
node e[100010];
int a[10010];
int first[10010];
bool v[10010];
ll leasthealth[10010];
int leastmoney[10010];
int q[10010],st=1,ed=2;
int road[50010][3];
void buildroad(int x,int y,int z)
{
len++;
e[len].x=x;
e[len].y=y;
e[len].z=z;
e[len].next=first[x];
first[x]=len;
}
int maxx(int x,int y){return x>y?x:y;}
int main()
{
scanf("%d %d %d",&n,&m,&k);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
memset(first,0,sizeof(first));
memset(leasthealth,63,sizeof(leasthealth));
memset(v,false,sizeof(v));
for(int i=1;i<=m;i++)
{
int x,y,z;
scanf("%d %d %d",&x,&y,&z);
buildroad(x,y,z);
buildroad(y,x,z);
}
//printf("\n");
//for(int i=1;i<=len;i++)
//printf("%d %d %d\n",e[i].x,e[i].y,e[i].z);
q[st]=n;
v[n]=true;
leasthealth[n]=1;
while(st!=ed)
{
int x=q[st];
//printf("%d ",x);
for(int i=first[x];i;i=e[i].next)
{
int y=e[i].y;
if(leasthealth[x]+(ll)(e[i].z)<leasthealth[y])
{
leasthealth[y]=leasthealth[x]+(ll)(e[i].z);
if(!v[y])
{
v[y]=true;
q[ed++]=y;
if(ed>n)ed=1;
}
}
}
st++;
if(st>n)st=1;
v[x]=false;
}
/*printf("\n");
for(int i=1;i<=n;i++)
printf("%d ",leasthealth[i]);*/
//printf("%lld ",leasthealth[1]);
if(leasthealth[1]>(ll)(k))
{
printf("AFK");
return 0;
}
st=1,ed=2;
q[st]=1;
int nowhealth[10010];
memset(nowhealth,0,sizeof(nowhealth));
memset(leastmoney,63,sizeof(leastmoney));
nowhealth[1]=k;
leastmoney[1]=a[1];
while(st!=ed)
{
int x=q[st];
for(int i=first[x];i;i=e[i].next)
{
int y=e[i].y;
if((nowhealth[x]-(ll)(e[i].z)>=leasthealth[y]&&maxx(leastmoney[x],a[y])<leastmoney[y])||
(maxx(leastmoney[x],a[y])==leastmoney[y]&&nowhealth[x]-(ll)(e[i].z)>=leasthealth[y]&&nowhealth[x]-(ll)(e[i].z)>nowhealth[y]))
//if(maxx(leastmoney[x],a[y])<leastmoney[y])
{
leastmoney[y]=maxx(leastmoney[x],a[y]);
if(nowhealth[y]<nowhealth[x]-e[i].z)nowhealth[y]=nowhealth[x]-e[i].z;
if(!v[y])
{
v[y]=true;
q[ed++]=y;
if(ed>n)ed=1;
}
}
}
st++;
if(st>n)st=1;
v[x]=false;
}
printf("%d",leastmoney[n]);
}
但这种思路是错的,比如以下数据,正确答案是5,但我的程序会输出6
7 8 12 1 4 3 1 6 5 1 1 2 2 1 3 4 3 4 3 2 4 2 4 5 2 4 6 4 5 7 2 6 7 3 画成图就是:
@lin_toto
可以加强一下数据吗。。
by Scarlet_Hypoc @ 2018-04-10 19:59:03
7 8 12
1
4
3
1
6
5
1
1 2 2
1 3 4
3 4 3
2 4 2
4 5 2
4 6 4
5 7 2
6 7 3
数据
by star_magic_young @ 2018-04-10 20:04:54
你氵过去了难道不发题解吗
by chen_zhe @ 2018-04-10 20:08:14
@666的brz 已增强
by D447H @ 2019-08-27 20:49:27
增强了
by Velix @ 2020-04-19 23:33:34
nb,卡掉了我的正解……