#Dijkstra,博弈论#ABC261 Ex - Game on Graph
分析
相当于是从任意出点出发到起点,设 \(dis[0/1][x]\) 表示先手/后手从 \(x\) 出发获得的最小/最大得分,
\(dis[0][x]=\min\{dis[1][y]+w\},dis[1][x]=\max\{dis[0][y]+w\}\)
而先手的最小得分可以直接用最短路实现,而 \(dis[1][x]\) 需要它的所有后继 \(dis[0][y]\),
因此记录出度直到它的后继全部计算完才将其丢入优先队列。
代码
#include <cstdio>
#include <cctype>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
const int N=200011;
struct rec{
int z,x; long long d;
bool operator <(const rec &t)const{
return d>t.d;
}
};
struct node{int y,w,next;}e[N];
priority_queue<rec>q;
int n,m,S,deg[N],as[N]; long long dis[2][N];
int iut(){
int ans=0; char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans;
}
int main(){
n=iut(),m=iut(),S=iut();
for (int i=1;i<=m;++i){
int x=iut(),y=iut(),w=iut();
e[i]=(node){x,w,as[y]},as[y]=i,++deg[x];
}
memset(dis[0],0x3f,sizeof(dis[0]));
memset(dis[1],0xcf,sizeof(dis[1]));
for (int i=1;i<=n;++i)
if (!deg[i]){
dis[0][i]=dis[1][i]=0;
q.push((rec){0,i,0});
q.push((rec){1,i,0});
}
while (!q.empty()){
rec t=q.top(); q.pop();
if (dis[t.z][t.x]!=t.d) continue;
if (!t.z){
for (int i=as[t.x];i;i=e[i].next){
dis[1][e[i].y]=max(dis[1][e[i].y],dis[0][t.x]+e[i].w);
if (--deg[e[i].y]==0) q.push((rec){1,e[i].y,dis[1][e[i].y]});
}
}else{
for (int i=as[t.x];i;i=e[i].next)
if (dis[0][e[i].y]>dis[1][t.x]+e[i].w){
dis[0][e[i].y]=dis[1][t.x]+e[i].w;
q.push((rec){0,e[i].y,dis[0][e[i].y]});
}
}
}
if (dis[0][S]<0x3f3f3f3f3f3f3f3f) printf("%lld\n",dis[0][S]);
else printf("INFINITY\n");
return 0;
}

浙公网安备 33010602011771号