[arc078f]Mole and Abandoned Mine

来源:互联网 发布:java 异或运算符 编辑:程序博客网 时间:2024/06/06 09:42

题目大意

一张无向带权连通图,删去边权和尽量小的边使得1->n路径唯一。

DP

设f[s,i]表示1->i,目前和1联通的集合是s,1->i不存在两条路,能保留的最大边权和。
转移分两种,一种是加一条桥,一种是给i挂一个集合。
f[s,i]+dis[i,j]>f[s,j]
还有f[s,i]+p[y]>f[s|y,i]其中y包含i。
p[y]表示一个集合保留内部所有边权和。

#include<cstdio>#include<algorithm>#define fo(i,a,b) for(i=a;i<=b;i++)#define two(i) (1<<(i-1))using namespace std;const int maxn=15+10,inf=1000000000;int f[(1<<16)+10][maxn],p[(1<<16)+10],id[(1<<16)+10];int dis[maxn][maxn];int i,j,k,l,r,s,t,n,m,now,all,ans,sum;int lowbit(int x){    return x&-x;}int main(){    scanf("%d%d",&n,&m);    fo(i,1,n) id[two(i)]=i;    all=(1<<n)-1;    fo(i,1,m){        scanf("%d%d%d",&j,&k,&t);        sum+=t;        dis[j][k]=dis[k][j]=t;    }    fo(i,1,all){        now=id[lowbit(i)];        p[i]=p[i-two(now)];        fo(j,now+1,n)            if ((i&two(j))) p[i]+=dis[now][j];    }    fo(i,0,n)        fo(j,0,all)            f[j][i]=-inf;    f[two(1)][1]=0;    ans=-inf;    fo(s,1,all){        fo(i,1,n){            r=s;            while (r){                if ((r&two(i))) f[s][i]=max(f[s][i],f[(s-r)|two(i)][i]+p[r]);                r=(r-1)&s;            }            fo(j,1,n)                if (!(s&two(j))&&dis[i][j]) f[s|two(j)][j]=max(f[s|two(j)][j],f[s][i]+dis[i][j]);        }        if ((s&two(n))) ans=max(ans,f[s][n]);    }    printf("%d\n",sum-ans);}