[AHOI2014/JSOI2014]骑士游戏 深入理解spfa

2019-04-09 17:44:36 浏览数 (1)

[AHOI2014/JSOI2014]骑士游戏

杀死魔物有两种方式 魔法或者物理攻击再让它去世

则 dis = min(魔法 , 物理 所有子代魔法);

就像dp,然而可能成环。考虑spfa成环距离必定大于最小距离(边为正数)。

一般spfa需要知道起点,这里不知道从哪里开始有最优解,就把所有点都加进去(貌似入度为零加了会更快?)

也不知道终点,则每次松弛成功就把它能影响到的结点再次入队。

代码语言:javascript复制
//深入理解spfa 
#include <bits/stdc  .h>
using namespace std;
#define ll long long
const int N = 250000;
ll dis[N],a[N];
vector<ll> from[N],to[N];
int book[N];
int n;
ll read(){
    ll x=0,sign=1;
    char c=getchar();
    while(c>'9'||c<'0'){
        if(c=='-') sign=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9'){
        x=x*10 c-'0';
        c=getchar();
    }
    return x*sign;
}
void spfa(){
	queue<int> q;
	for(int i=1;i<=n;i  )book[i]=1,q.push(i);//不知道从哪开始为最优解
	while(!q.empty()){
		int u = q.front(); book[u] = 0; q.pop();
		ll temp = a[u];
		for(int i=0;i<from[u].size();i  )temp =dis[from[u][i]];
		if(dis[u]<=temp)continue;
		dis[u] = temp;
		for(int i=0;i<to[u].size();i  ){//松弛成功 可以影响到的点重新入队 
			if(!book[to[u][i]]){
				q.push(to[u][i]);
				book[to[u][i]]=1;
			}
		}
	} 
	
} 
int main()
{
	n = read();
	for(int i=1;i<=n;i  ){
		int r,u,v;
		a[i] = read(); dis[i] = read(); r=read(); //初始化dis为魔法值 
		while(r--){
			v = read();
			from[i].push_back(v);//i 可以到达v 
			to[v].push_back(i);//v可以影响到i 
		}
	}
	spfa();
	printf("%lld",dis[1]);
	return 0;
 } 

0 人点赞