【BZOJ3590】[Snoi2013]Quare 状压DP

题解:

一道比较水的题

但这个测试数据极弱我也不知道我的代码正确性是不是有保证

构成一个边双联通

可以由两个有一个公共点的边双联通或者一个边双加一条链构成

所以我们需要要预处理出所有环

令f[i][j][k]表示起点为i,终点为j,经过点的状态为k,这样递推

那么最后环就是加上j-i这条边就可以了

但是注意一个二元环,一个为最长边一个为次长边

其他环都不会用到次长边

代码:

#include <bits/stdc++.h>
using namespace std;
#define IL inline
#define rint register int
#define dep(i,t,h) for (rint i=t;i>=h;i--)
#define rep(i,h,t) for (rint i=h;i<=t;i++)
char ss[1<<24],*A=ss,*B=ss;
IL char gc()
{
  return A==B&&(B=(A=ss)+fread(ss,1,1<<24,stdin),A==B)?EOF:*A++;
}
template<class T>void read(T &x)
{
  rint f=1,c; while (c=gc(),c<48||c>57) if (c=='-') f=-1; x=(c^48);
  while(c=gc(),c>47&&c<58) x=(x<<3)+(x<<1)+(c^48); x*=f; 
}
void umin(int &x,int y)
{
  if (x>y) x=y;
}
int dp[15][15][1<<14],ff[1<<14],f[20][20][2],n,m;
bool tf[1<<14];
const int INF=1e9;
int main()
{
  int T;
  read(T);
  rep(tt,1,T)
  {
    read(n); read(m);
    rep(i,1,n) 
      rep(j,1,n)
        f[i][j][0]=f[i][j][1]=INF;
    rep(i,1,m)
    {
      int x,y,z;
      read(x); read(y); read(z);
      if (z<=f[x][y][0]) 
      f[x][y][1]=f[x][y][0],f[x][y][0]=z,
      f[y][x][1]=f[y][x][0],f[y][x][0]=z;
      else if (z<f[x][y][1]) f[x][y][1]=z,f[y][x][1]=z;
    }
    rep(i,1,n)
      rep(j,1,n)
        rep(k,1,(1<<n)-1) dp[i][j][k]=INF;
    rep(i,1,n) dp[i][i][(1<<(i-1))]=0;
    rep(i,1,(1<<n)-1)
    {
      int a[100];
      int cnt=0;
      rep(j,1,n)
        if ((i>>(j-1))&1) a[++cnt]=j;
      rep(i1,1,cnt)
        rep(j1,1,cnt)
          rep(k,1,n)
            if (!((i>>(k-1))&1))
              umin(dp[a[i1]][k][i|(1<<(k-1))],dp[a[i1]][a[j1]][i]+f[a[j1]][k][0]);
    }
    rep(i,1,(1<<n)-1) tf[i]=0;
        rep(i,1,(1<<n)-1) ff[i]=INF;
    rep(i,1,n)
      rep(j,1,n)
        if (i!=j)
          tf[(1<<(i-1))+(1<<(j-1))]=1,
          ff[(1<<(i-1))+(1<<(j-1))]=min(INF,f[i][j][0]+f[i][j][1]);
    rep(i,1,(1<<n)-1)
      if (!tf[i])
        rep(j,1,n)
          rep(k,1,n)
            umin(ff[i],dp[j][k][i]+f[j][k][0]);
    rep(i,1,(1<<n)-1)
      for (int j=i;j;j=i&(j-1))
        rep(k,1,n)
          if (j&(1<<(k-1)))
            umin(ff[i],ff[(i^j)|(1<<(k-1))]+ff[j]);
    if (ff[(1<<n)-1]!=INF) cout<<ff[(1<<n)-1]<<endl;
    else cout<<"impossible"<<endl; 
  }
  return 0; 
}

 

转载于:https://www.cnblogs.com/yinwuxiao/p/9317508.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值