【JZOJ 5442】【NOIP2017提高A组冲刺11.1】荒诞

来源:互联网 发布:北京80坐标系数据 编辑:程序博客网 时间:2024/05/22 11:54

Description

我的灵魂与我之间的距离如此遥远,而我的存在却如此真实。
——加缪《局外人》
我醒来的时候,发现满天星斗照在我的脸上。田野上的声音一直传到我的耳畔。夜的气味,土地的气味,海盐的气味,使我的两鬓感到清凉。这沉睡的夏夜的奇妙安静,像潮水一般浸透我的全身。这时,长夜将尽,汽笛叫了起来。它宣告有些人踏上旅途,要去一个从此和我无关痛痒的世界。
这时我在想一个问题:我有一个n个点,m条边的无向图,第i个点建立一个旅游站点的费用是c_i。特别地,这张图中的任意两点间不存在节点数超过10的简单路径。
为了把一切都做得完善,为了使我感到不那么孤独,我想要建造一些旅游站点使得每个点要么建立了旅游站点,要么与它有边直接相连的点里至少有一个点建立了旅游站点。我还希望这个建造方案总花费尽量少。
请求出这个花费。

Solution

题目里那个奇怪的条件就是告诉你,这张图生成的dfs树的深度不会超过10,
那么就很自然的想到了状压DP,

设f[i][s]表示做到了第i层,状态为S,S是一个3进制数,0表示没有选但被覆盖到了,1表示选了,2表示没有选且没有被覆盖到,

转移显然,

复杂度:注意,并不是O(n310),也就是O(20000310),仔细算你会发现是O(n/10311),也就是O(2000311),才3.5个亿,卡卡常3S不虚,

复杂度仔细算!!!仔细算!!!仔细算!!!

Code

#include <cstdio>#include <algorithm>#include <cstring>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fod(i,a,b) for(int i=a;i>=b;i--)#define efo(i,q) for(int i=A[q];i;i=B[i][0])#define min(q,w) ((q)<(w)?(q):(w))using namespace std;const int N=200500,INF=2139062143;int read(int &n){    scanf("%d",&n);    return n;}int n,m,ans;int co[N],C[N];bool z[N];int B[3*N][2],A[N],B0;int er[20];int f[15][1772000];void link(int q,int w){    B[++B0][0]=A[q],A[q]=B0,B[B0][1]=w;    B[++B0][0]=A[w],A[w]=B0,B[B0][1]=q;}bool OK(int q,int w){    for(;q;q/=3,w/=3)if(q%3==1&&w%3)return 1;    return 0;}int JA(int q,int w,int n){    fo(i,1,n)if((q/er[i])%3==2&&(w/er[i])%3)q-=2*er[i];    return q;}void dfs(int q,int c){    int t=er[c];    efo(i,q)if(C[B[i][1]])if((t/er[C[B[i][1]]])%3==0)t+=er[C[B[i][1]]];    C[q]=c;    fo(i,0,er[c]-1)if(f[c-1][i]<INF)    {        if(OK(i,t))f[c][i]=f[c-1][i];            else f[c][i+2*er[c]]=f[c-1][i];        int t1=JA(i,t,c-1)+er[c];        f[c][t1]=min(f[c][t1],f[c-1][i]+co[q]);    }    efo(i,q)if(!C[B[i][1]])    {        dfs(B[i][1],c+1);        fo(j,0,er[c+1]-1)        {            f[c][j]=min(f[c+1][j],f[c+1][j+er[c+1]]);            f[c+1][j]=f[c+1][j+er[c+1]]=f[c+1][j+er[c+1]*2]=INF;        }    }}int main(){    freopen("absurdity.in","r",stdin);    freopen("absurdity.out","w",stdout);    int q,w;    er[1]=1;fo(i,2,15)er[i]=er[i-1]*3;    read(n),read(m);    fo(i,1,n)read(co[i]);    fo(i,1,m)read(q),read(w),link(q,w);    ans=0;    memset(f,127,sizeof(f));    memset(f[0],0,sizeof(f[0]));    fo(i,1,n)if(!C[i])    {        dfs(i,1);        ans+=min(f[1][0],f[1][1]);        f[1][0]=f[1][1]=f[1][2]=INF;    }    printf("%d\n",ans);    return 0;}
原创粉丝点击