您的位置:首页 > 其它

[2017纪中11-1]荒诞 欧拉序+状压DP

2017-11-02 15:33 357 查看
题面

题解

太巧妙了。。。图上还能DP。。。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#define chkmin(a,b) a=min(a,b)
using namespace std;
const int maxn=100010;
int n,m,c[maxn],d[maxn],f[12][60000],ans=0,mi[12];
struct edge
{
int t;
edge *next;
}*con[maxn];
int T(int s,int w)
{
return s/mi[w]%3;
}
int mx(int a,int b,int d)
{
for(int i=0;i<=d;i++)
{
int ta=T(a,i),tb=T(b,i);
if(tb>ta) a+=(tb-ta)*mi[i];
}
return a;
}
bool lk(int a,int b,int d)
{
for(int i=0;i<=d;i++)
if(T(a,i)==1&&T(b,i)==2) return 1;
return 0;
}
void ins(int x,int y)
{
edge *p=new edge;
p->t=y;
p->next=con[x];
con[x]=p;
}
void dfs(int v)
{
int fff=0,dv=d[v];
memset(f[dv],0x3f,sizeof(int)*mi[dv+1]);
for(edge *p=con[v];p;p=p->next)
if(d[p->t]!=-1)  fff+=mi[d[p->t]];
for(int s=0;s<=mi[dv]-1;s++)
{
int fas=((dv==0)?0:f[dv-1][s]);
if(fas<0x3f3f3f3f)
{
if(lk(fff,s,dv-1)) f[dv][s+mi[dv]]=fas;
else f[dv][s]=fas;
chkmin(f[dv][mx(fff,s,dv-1)+(mi[dv]<<1)],fas+c[v]);
}
}
for(edge *p=con[v];p;p=p->next)
if(d[p->t]==-1)
d[p->t]=dv+1,dfs(p->t);
if(dv!=0)
for(int s=0;s<=(mi[dv]-1);s++)
f[dv-1][s]=min(f[dv][s+mi[dv]],f[dv][s+(mi[dv]<<1)]);
}
int main()
{
mi[0]=1;
for(int i=1;i<=10;i++)
mi[i]=mi[i-1]*3;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&c[i]);
for(int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
ins(x,y);
ins(y,x);
}
memset(d,-1,sizeof(d));
for(int i=1;i<=n;i++)
if(d[i]==-1)
{
d[i]=0;
dfs(i);
ans+=min(f[0][1],f[0][2]);
}
printf("%d",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: