题解P4042 [AHOI2014/JSOI2014]骑士游戏

Posted glq_C

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了题解P4042 [AHOI2014/JSOI2014]骑士游戏相关的知识,希望对你有一定的参考价值。

【P4042 [AHOI2014/JSOI2014]骑士游戏】

最短路好题。
如果考虑dp的话,设\\(f_i\\)表示第i个怪物被消灭的最小代价,那么显然有\\(f_i=min(k_i,s_i+\\sum\\limits_{j=1}^{r_i}f_{vj})\\)
但是题目中,怪物会形成一个环,具有后效性。
这里有两种方法:

  1. 借助spfa思想,既然不知道从哪开始转移,那就全部进队,全都转移,不断进行松弛,直到队列为空。但是这里有一点需要注意,传统的spfa进行更新时,都是一对多的更新,但这个题目中的更新属于多对一的更新。因此队列中不再维护“可能更新其他点的点”,而是维护“可能被其他点更新的点”。
  2. 借助dij的思想,\\(f_i\\)能从第二个式子转移的必要条件是任意\\(f_{vj},有f_{vj}<f_i\\),于是我们可以对dp值建一个堆,每次取最小值去更新其他点,如果被更新的dp值已经更新完了,将其加入堆内;如果其需要更新的dp值已经被弹出,那么显然有那个dp值小于当前dp值所以更新无用

Dij

// luogu-judger-enable-o2
#include<bits/stdc++.h>
using namespace std;
#define rep( i, s, t ) for( register int i = s; i <= t; ++ i )
#define re register
#define int long long
int read() {
	char cc = getchar(); int cn = 0, flus = 1;
	while(cc < \'0\' || cc > \'9\') {  if( cc == \'-\' ) flus = -flus;  cc = getchar();  }
	while(cc >= \'0\' && cc <= \'9\')  cn = cn * 10 + cc - \'0\', cc = getchar();
	return cn * flus;
}
const int N = 2e5 + 5 ; 
const int M = 1e6 + 5 ; 
int n, s[N], K[N], dp[N], vis[N], ans[N], R[N] ;
vector<int> mp[N] ; 
struct node {
	int id, w ; 
	bool operator < ( const node& x ) const {
		return w > x.w ; 
	}
};
priority_queue<node> q ; 
signed main()
{
	n = read() ; int x, siz ; 
	rep( i, 1, n ) 	{
		s[i] = read(), K[i] = read(), R[i] = read() ;
		rep( j, 1, R[i] ) x = read(), mp[x].push_back(i) ; 
		q.push((node){ i, K[i] }), dp[i] = s[i] ;
	}
	while( !q.empty() ) {
		int u = q.top().id, w = q.top().w ; q.pop() ; 
		if( vis[u] ) continue ; 
		vis[u] = 1, ans[u] = w, siz = mp[u].size() - 1 ; 
		rep( i, 0, siz ) {
			int v = mp[u][i] ; 
			if( vis[v] || dp[v] > K[v] ) continue ; 
			R[v] --, dp[v] += w ;
			if( R[v] == 0 ) q.push((node){ v, dp[v] }) ;
		}
	}
	printf("%lld\\n", ans[1] ) ;
	return 0;
}

Spfa

#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read()
{
	register int x=0,w=1;
	register char ch=getchar();
	while((ch<\'0\'||ch>\'9\')&&ch!=\'-\') ch=getchar();
	if(ch==\'-\'){ch=getchar();w=-1;}
	while(ch>=\'0\'&&ch<=\'9\'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();	}
	return x*w;
}
const int N=2e5+100;
int n,d[N],s[N];
vector<int>son[N],fa[N];
int vis[N];
void spfa()
{
	queue<int>q;
	memset(vis,1,sizeof vis);
	for(int i=1;i<=n;++i) q.push(i);
	while(q.size())
	{
		int x=q.front();q.pop();
		vis[x]=0;
		int w=s[x];
		for(int i=0;i<son[x].size();++i){
			w+=d[son[x][i]];
		}
		if(w<d[x]){
			d[x]=w;
			for(int i=0;i<fa[x].size();++i){
				int y=fa[x][i];
				if(vis[y]==0) {
					vis[y]=1;
					q.push(y);
				}
			}
		}
	}
}
void add(int x,int y)
{
     son[x].push_back(y);
     fa[y].push_back(x);
}
signed main()
{
    n=read();
    for(int i=1;i<=n;++i)
    {
    	s[i]=read();
    	d[i]=read();
    	int x=read(),y;
    	while(x--){
    		y=read();
    		add(i,y);
		}
	}
	spfa();
	cout<<d[1];
	return 0;
}

bzoj3481题解

答案等于$\sum_{d|(P,Q)} d\times \phi (P/d)$设$P=\prod{i=1}^{t}p_i^m_i$,$(P,Q)=\prod_{i=1}^t p_i^k_i$(markdown莫名崩掉了,凑活着看吧)答案就等于$P=\prod p_i^{m_i-1}\times((k_i+1)(p_i-1)+[k_i=m_i])$

只用pollard-rho分解一下质因数就可以了。

注意$Q_i$可以等于0!我没注意就又wa又re一时爽,提交了50次,只能明天交了。。。

以上是关于题解P4042 [AHOI2014/JSOI2014]骑士游戏的主要内容,如果未能解决你的问题,请参考以下文章

luogu P4042 [AHOI2014/JSOI2014]骑士游戏

AHOI2014/JSOI2014 奇怪的计算器

「AHOI2014/JSOI2014」拼图

「AHOI2014/JSOI2014」支线剧情

「AHOI2014/JSOI2014」骑士游戏

[AHOI2014/JSOI2014]骑士游戏