网上竟然没有能看的懂的解释,我也是醉了
搞了好几个小时才找着一份代码,硬是看懂了
思路:记一个dis[i][j]数组,i表示节点,j表示时间是奇数还是偶数,0是偶数,1是奇数
某一个点的状态是由上一秒转移来的,而这两秒一定一个是奇数一个是偶数,所以1状态由0转移,0状态由1转移,黑洞需要翻转,而奇数秒的状态一定是被反转了的,偶数是没反转的,而这个可以用异或来搞定
因为0^1=1,1^1==0
而判断起点也是用异或
如果起点是白洞,偶数次之后还是白洞,奇数次后变成了黑洞,因为0^0=0,0^1=1,1^0=1,1^1=0
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586 | #include<iostream>#include<cstring>#include<cstdio>#include<queue>#include<cmath>using names 大专栏 伊吹萃香_(虫洞)pace std;struct st{ int s; bool f;};int n,m;int vis[19999][2],dis[19999][2],head[1999],nex[19999],cost[19999],to[199999],w[19999],tot,col[199999],s[19999];deque <st> q;void add(int x,int y,int z){ tot++; nex[tot]=head[x]; to[tot]=y; cost[tot]=z; head[x]=tot;} int dist(int stt,int too,bool ff)//判断起点{ int sf=col[stt]^ff; int tf=col[too]^ff; int ww=abs(w[stt]-w[too]); if(sf==tf)return 0; if(sf==1) return ww; else return -ww;}void spfa(int ss){ dis[ss][0]=0; vis[ss][0]=1; q.push_back((st){ss,0}); while(!q.empty()) { st o=q.front();q.pop_front(); int x=o.s; vis[x][o.f]=0; for(int i=head[x];i;i=nex[i]) { int tmp=to[i]; if(dis[tmp][o.f^1]>dis[x][o.f]+max(cost[i]+dist(x,tmp,o.f),0)) { dis[tmp][o.f^1]=dis[x][o.f]+max(cost[i]+dist(x,tmp,o.f),0); if(!vis[tmp][o.f^1]) { if(dis[tmp][o.f^1]<=dis[q.front().s][q.front().f]) q.push_front((st){tmp,o.f^1}); else q.push_back((st){tmp,o.f^1}); vis[tmp][o.f^1]=1; } } } if(dis[x][o.f^1]>dis[x][o.f]+(col[x]^o.f)*s[x]) { dis[x][o.f^1]=dis[x][o.f]+(col[x]^o.f)*s[x]; if(!vis[x][o.f^1]) { if(dis[x][o.f^1]<=dis[q.front().s][q.front().f]) q.push_front((st){x,o.f^1}); else q.push_back((st){x,o.f^1}); vis[x][o.f^1]=1; } } }}int main(){ memset(dis,127,sizeof dis); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&col[i]); for(int i=1;i<=n;i++) scanf("%d",&w[i]); for(int i=1;i<=n;i++) scanf("%d",&s[i]); for(int i=1;i<=m;i++) { int x,y,z; scanf("%d%d%d",&x,&y,&z); add(x,y,z); } spfa(1); printf("%d",min(dis[n][0],dis[n][1]));} |