专栏文章
题解:P4796 [BalticOI 2018] 路径
P4796题解参与者 3已保存评论 2
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 2 条
- 当前快照
- 1 份
- 快照标识符
- @min910hq
- 此快照首次捕获于
- 2025/12/01 22:32 3 个月前
- 此快照最后确认于
- 2025/12/01 22:32 3 个月前
P4796 [BalticOI 2018] 路径
- 方法:记忆化搜索。
- 首先根据题意,可以先打个暴搜,可以得到 分。
暴力搜索
CPP il void dfs(int u,int fa){
if(vis[a[u]]) return ;
vis[a[u]]=1;
if(fa) ++ans;
for(int v:g[u]){
if(v==fa) continue;
dfs(v,u);
}
vis[a[u]]=0;
}
- 然后考虑优化,注意到一个点可能会遍历多次,并且状态可能一致(即相同颜色集合),考虑用记忆化数组存储,第一维表示点,第二维表示颜色集合,由于 ,可以用状压来表示,转移可以用以下式子表示:
- 最后答案就是 ,因为路径长 ,所以减去 。总复杂度为 。
code
CPP#include<bits/stdc++.h>
#define il inline
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
il ll read(){
ll x=0;bool f=0;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=1;ch=getchar();}
while(isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
return f?-x:x;
}
const int N=3e5+5;
int a[N];
vector<int> g[N];
ll mem[N][1<<5];
int n,m,k;
il void solve();
int main()
{
// freopen("path.in","r",stdin);
// freopen("path.out","w",stdout);
solve();
return 0;
}
il ll dfs(int u,int fa,int val){
if((val&(1<<(a[u]-1)))||a[u]>k) return 0;
int p=val|(1<<(a[u]-1));
if(mem[u][p]!=-1) return mem[u][p];
ll res=1;
for(int v:g[u]){
if(v==fa) continue;
res+=dfs(v,u,p);
}
return mem[u][p]=res;
}
il void solve(){
n=read(),m=read(),k=read();
memset(mem,-1,sizeof(mem));
for(int i=1;i<=n;++i) a[i]=read();
for(int i=1,u,v;i<=m;++i)
u=read(),v=read(),
g[u].push_back(v),g[v].push_back(u);
ll ans=0;
for(int i=1;i<=n;++i) ans+=dfs(i,0,0);
printf("%lld\n",ans-n);
}
完结撒花。
相关推荐
评论
共 2 条评论,欢迎与作者交流。
正在加载评论...