「题目描述」
N个虫洞,M条单向跃迁路径。从一个虫洞沿跃迁路径到另一个虫洞需要消耗一定量的燃料和1单位时间。虫洞有白洞和黑洞之分。设一条跃迁路径两端的虫洞质量差为delta。
从白洞跃迁到黑洞,消耗的燃料值减少delta,若该条路径消耗的燃料值变为负数的话,取为0。
从黑洞跃迁到白洞,消耗的燃料值增加delta。
路径两端均为黑洞或白洞,消耗的燃料值不变化。
作为压轴题,自然不会是如此简单的最短路问题,所以每过1单位时间黑洞变为白洞,白洞变为黑洞。在飞行过程中,可以选择在一个虫洞停留1个单位时间,如果当前为白洞,则不消耗燃料,否则消耗s[i]的燃料。现在请你求出从虫洞1到N最少的燃料消耗,保证一定存在1到N的路线。
「输入格式」
第1行:2个正整数N,M
第2行:N个整数,第i个为0表示虫洞i开始时为白洞,1表示黑洞。
第3行:N个整数,第i个数表示虫洞i的质量w[i]。
第4行:N个整数,第i个数表示在虫洞i停留消耗的燃料s[i]。
第5..M+4行:每行3个整数,u,v,k,表示在没有影响的情况下,从虫洞u到虫洞v需要消耗燃料k。
「输出格式」
一个整数,表示最少的燃料消耗。
「样例输入」
4 5
1 0 1 0
10 10 100 10
5 20 15 10
1 2 30
2 3 40
1 3 20
1 4 200
3 4 200
「样例输出」
130
「数据范围」
对于30%的数据: 1<=N<=100,1<=M<=500
对于60%的数据: 1<=N<=1000,1<=M<=5000
对于100%的数据: 1<=N<=5000,1<=M<=30000
其中20%的数据为1<=N<=3000的链
1<=u,v<=N, 1<=k,w[i],s[i]<=200
「样例说明」
按照1->3->4的路线。
题解
首先每个点拆成黑白点
本来一个黑到一个白连边v+delta
但是因为每秒会变色,所以是一个黑到一个黑连边v+delta
条件是俩点的初始颜色不同
其余的同理
然后最短路。。。
一开始spfa写错只有80分好伤心。。
C++
#include
#include
#include
#include
#define ll long long
using namespace std;
inline int read()
{
char ch=getchar();
int f=1,x=0;
while(!(ch>='0'&&ch<='9')){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+(ch-'0');ch=getchar();}
return x*f;
}
int n,m,cnt;
int q[10005];ll d[10005];
bool mp[10005],inq[10005];
int w[10005],s[10005];
int h[10005],head[10005];
struct data{int to,next,v;}ed[100005],e[200005];
void ins(int u,int v,int w)
{ed[++cnt].to=v;ed[cnt].v=w;ed[cnt].next=h[u];h[u]=cnt;}
void insert(int u,int v,int w)
{e[++cnt].to=v;e[cnt].v=w;e[cnt].next=head[u];head[u]=cnt;}
void build(int x)
{
insert(x,x+n,s[x]);
insert(x+n,x,0);
for(int i=h[x];i;i=ed[i].next)
{
int de=abs(w[x]-w[ed[i].to]);
if(mp[x]!=mp[ed[i].to])
{
insert(x,ed[i].to,ed[i].v+de);
insert(x+n,ed[i].to+n,max(0,ed[i].v-de));
}
else
{
insert(x,ed[i].to+n,ed[i].v);
insert(x+n,ed[i].to,ed[i].v);
}
}
}
void spfa()
{
int t=0,w=1;
memset(d,127,sizeof(d));
if(mp[1]){q[0]=1;d[1]=0;inq[1]=1;}
else {q[0]=n+1;d[n+1]=0;inq[n+1]=1;}
while(t!=w)
{
int now=q[t];t++;if(t==10001)t=0;
for(int i=head[now];i;i=e[i].next)
{
if(e[i].v+d[now]
{
d[e[i].to]=d[now]+e[i].v;
if(!inq[e[i].to])
{
inq[e[i].to]=1;
q[w++]=e[i].to;
if(w==10001)w=0;
}
}
}
inq[now]=0;
}
printf("%I64d",min(d[n],d[n+n]));
}
int main()
{
//freopen("holes.in","r",stdin);
//freopen("holes.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
mp[i]=read();
for(int i=1;i<=n;i++)
w[i]=read();
for(int i=1;i<=n;i++)
s[i]=read();
for(int i=1;i<=m;i++)
{
int u=read(),v=read(),w=read();
ins(u,v,w);
}
cnt=0;
for(int i=1;i<=n;i++)
build(i);
spfa();
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#include
#include
#include
#include
#define ll long long
usingnamespacestd;
inlineintread()
{
charch=getchar();
intf=1,x=0;
while(!(ch>='0'&&ch<='9')){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+(ch-'0');ch=getchar();}
returnx*f;
}
intn,m,cnt;
intq[10005];lld[10005];
boolmp[10005],inq[10005];
intw[10005],s[10005];
inth[10005],head[10005];
structdata{intto,next,v;}ed[100005],e[200005];
voidins(intu,intv,intw)
{ed[++cnt].to=v;ed[cnt].v=w;ed[cnt].next=h[u];h[u]=cnt;}
voidinsert(intu,intv,intw)
{e[++cnt].to=v;e[cnt].v=w;e[cnt].next=head[u];head[u]=cnt;}
voidbuild(intx)
{
insert(x,x+n,s[x]);
insert(x+n,x,0);
for(inti=h[x];i;i=ed[i].next)
{
intde=abs(w[x]-w[ed[i].to]);
if(mp[x]!=mp[ed[i].to])
{
insert(x,ed[i].to,ed[i].v+de);
insert(x+n,ed[i].to+n,max(0,ed[i].v-de));
}
else
{
insert(x,ed[i].to+n,ed[i].v);
insert(x+n,ed[i].to,ed[i].v);
}
}
}
voidspfa()
{
intt=0,w=1;
memset(d,127,sizeof(d));
if(mp[1]){q[0]=1;d[1]=0;inq[1]=1;}
else{q[0]=n+1;d[n+1]=0;inq[n+1]=1;}
while(t!=w)
{
intnow=q[t];t++;if(t==10001)t=0;
for(inti=head[now];i;i=e[i].next)
{
if(e[i].v+d[now]
{
d[e[i].to]=d[now]+e[i].v;
if(!inq[e[i].to])
{
inq[e[i].to]=1;
q[w++]=e[i].to;
if(w==10001)w=0;
}
}
}
inq[now]=0;
}
printf("%I64d",min(d[n],d[n+n]));
}
intmain()
{
//freopen("holes.in","r",stdin);
//freopen("holes.out","w",stdout);
scanf("%d%d",&n,&m);
for(inti=1;i<=n;i++)
mp[i]=read();
for(inti=1;i<=n;i++)
w[i]=read();
for(inti=1;i<=n;i++)
s[i]=read();
for(inti=1;i<=m;i++)
{
intu=read(),v=read(),w=read();
ins(u,v,w);
}
cnt=0;
for(inti=1;i<=n;i++)
build(i);
spfa();
return0;
}