Codeforces Gym

来源:互联网 发布:淘宝怎么发布定制商品 编辑:程序博客网 时间:2024/05/21 16:59

题意:给你n个点m条边的图,再给出p个强盗和k,表示点距离强盗最短距离小于等于k的时候需要收钱。问从起点s到终点t的最小花费,每条边的长度为1

题解:首先对每个强盗做bfs,对bfs到的点打上该强盗的标记。然后状态压缩10个强盗,表示能否经过这些海盗从s走到t,由于状态压缩枚举所有情况,所以对所有s能到t的情况取min,就能得到答案。

AC代码:

#include<stdio.h>#include<vector>#include<queue>#include<string.h>#define N 100005using namespace std;typedef long long ll;vector<ll>vt[N];ll have[N];ll n,m,K,p;ll a[15],v[15];ll mark[N];ll mm[15];ll s,t;ll ans=1000000000000ll;struct node{ll v,w;node(){}node(ll v,ll w){this->v=v;this->w=w;}};void bfs(ll u,ll biao){queue<node>que;memset(mark,0,sizeof(mark));que.push(node(u,0));mark[u]=1;while(!que.empty()){node k=que.front();que.pop();have[k.v]|=biao;if(k.w==K)continue;for(ll i=0;i<vt[k.v].size();i++){ll to=vt[k.v][i];if(mark[to]==1)continue;mark[to]=1;que.push(node(to,k.w+1));}}}ll bfs2(){queue<ll>que;memset(mark,0,sizeof(mark));que.push(s);mark[s]=1;while(!que.empty()){ll k=que.front();que.pop();for(ll i=0;i<vt[k].size();i++){ll to=vt[k][i];if(mark[to]==1)continue;if(have[to]==0){if(to==t)return 1;mark[to]=1;que.push(to);}else {int flag=1;for(ll j=0;j<p;j++){if(!(have[to]&(1<<j)))continue;if((have[to]&(1<<j))&&mm[j]);else flag=0;}if(flag==0)continue;if(to==t)return 1;mark[to]=1;que.push(to);}}}return 0;}int main(){scanf("%lld%lld%lld%lld",&n,&m,&p,&K);for(ll i=1;i<=p;i++)scanf("%lld",&a[i]);for(ll i=1;i<=p;i++)scanf("%lld",&v[i]);for(ll i=0;i<m;i++){ll u,v;scanf("%lld%lld",&u,&v);vt[u].push_back(v);vt[v].push_back(u);}for(ll i=1;i<=p;i++)bfs(a[i],(1<<(i-1)));scanf("%lld%lld",&s,&t);if(s==t){ll pay=0;for(ll j=0;j<p;j++)if(have[t]&(1<<j))pay+=v[j+1];printf("%lld\n",pay);return 0;}for(ll state=0;state<(1<<p);state++){memset(mm,0,sizeof(mm));ll pay=0;for(ll j=0;j<p;j++)if(state&(1<<j)){mm[j]=1;pay+=v[j+1];}if(have[s]!=0&&have[s]!=state)continue;if(pay<ans)if(bfs2())ans=pay;}printf("%lld\n",ans);}