题解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})\\)
但是题目中,怪物会形成一个环,具有后效性。
这里有两种方法:
- 借助spfa思想,既然不知道从哪开始转移,那就全部进队,全都转移,不断进行松弛,直到队列为空。但是这里有一点需要注意,传统的spfa进行更新时,都是一对多的更新,但这个题目中的更新属于多对一的更新。因此队列中不再维护“可能更新其他点的点”,而是维护“可能被其他点更新的点”。
- 借助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]骑士游戏的主要内容,如果未能解决你的问题,请参考以下文章