\(\\\)

\(Description\)


\(N\)个点\(M\)条边的有向图,求从\(0\)号节点出发,\(N-1\)号节点结束,且图中每个点至多经过一次的最长路。

  • \(N\in[2,18]\)

\(\\\)

\(Solution\)


状压\(DP\)最长路。

记忆化搜索的写法,可以通过调整回溯值来保证终点一定是\(N-1\)号节点\((\)无法到达就返回负无穷\()\)。

直接状压\(DP\)初始化要注意设成负无穷,然后统计答案只计算当前点是\(N-1\)号点的情况。

\(\\​\)

\(Code\)


\(\\\)

记搜版本

#include<cmath>
#include<cstdio>
#include<cctype>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 20
#define M 410
#define R register
#define gc getchar
#define inf 2000000000
using namespace std; inline int rd(){
int x=0; bool f=0; char c=gc();
while(!isdigit(c)){if(c=='-')f=1;c=gc();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=gc();}
return f?-x:x;
} int n,m,tot,hd[N],f[1<<N][N];
struct edge{int w,to,nxt;}e[M]; inline void add(int u,int v,int w){
e[++tot].to=v; e[tot].w=w;
e[tot].nxt=hd[u]; hd[u]=tot;
} int dfs(int u,int s){
if(u==n-1) return 0;
if(f[s][u]>0) return f[s][u];
int ans=-inf;
for(R int i=hd[u],v;i;i=e[i].nxt){
v=e[i].to;
if(s&(1<<v)) continue;
ans=max(ans,e[i].w+dfs(v,(s|(1<<v))));
}
return f[s][u]=ans;
} int main(){
n=rd(); m=rd();
for(R int i=1,u,v,w;i<=m;++i){
u=rd(); v=rd(); w=rd(); add(u,v,w);
}
printf("%d\n",dfs(0,1));
return 0;
}

\(\\\)

直接状压版本

#include<cmath>
#include<cstdio>
#include<cctype>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 20
#define M 410
#define R register
#define gc getchar
#define inf 2000000000
using namespace std; inline int rd(){
int x=0; bool f=0; char c=gc();
while(!isdigit(c)){if(c=='-')f=1;c=gc();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=gc();}
return f?-x:x;
} int n,m,tot,ans,hd[N],f[1<<N][N];
struct edge{int w,to,nxt;}e[M]; inline void add(int u,int v,int w){
e[++tot].to=v; e[tot].w=w;
e[tot].nxt=hd[u]; hd[u]=tot;
} int main(){
n=rd(); m=rd();
for(R int i=1,u,v,w;i<=m;++i){
u=rd(); v=rd(); w=rd(); add(u,v,w);
}
int lim=(1<<n);
for(R int s=0;s<lim;++s)
for(R int u=0;u<n;++u) f[s][u]=-inf;
f[1][0]=0;
for(R int s=1;s<lim;++s){
for(R int u=0;u<n;++u)
if(((s&(1<<u))>0)&&f[s][u]>=0)
for(R int i=hd[u],v;i;i=e[i].nxt){
v=e[i].to; if((s&(1<<v))>0) continue;
f[s|(1<<v)][v]=max(f[s|(1<<v)][v],f[s][u]+e[i].w);
}
ans=max(ans,f[s][n-1]);
}
printf("%d\n",ans);
return 0;
}

最新文章

  1. 参数table_open_cache
  2. Cwinux源码解析系列
  3. [codevs2070]爱情之路
  4. PHP 防止表单重复提交
  5. 启动Print Spooler服务提示:&quot;错误1068,依存服务或无法启动&quot;
  6. easyui accordion—手风琴格子始终展开和多个格子展开
  7. 《云大课程助手》Android刷课工具来袭
  8. 用perl对字符串进行全角转半角操作
  9. pl sql developer登陆界面找不到oracle数据库选项
  10. Exception testing
  11. Linux下multipath多路径配置
  12. [Python笔记][第三章Python选择与循环]
  13. CCProgressTo 和CCProgressTimer
  14. html5权威指南:标记文字、组织内容、文档分节
  15. redhat 安装GCC-4.8.3
  16. Java 8 lambda初试
  17. Wpf DataGridCheckBoxColumn 问题
  18. Spring框架碰壁日常更新
  19. CSS之使用display:inline-block来布局
  20. C#绘图:带背景,拖鼠标画矩形和直线

热门文章

  1. JVM定位程序假死或cpu占用高的线程
  2. 断路器监控(Hystrix Dashboard)
  3. Linux学习日志--文件搜索命令
  4. html5 虚拟键盘弹出挡住底部的输入框解决方案
  5. OSS与文件系统的对比
  6. 获取发布的头条的url,避免点击打开新的页面
  7. SQL Server 运行计划操作符具体解释(1)——断言(Assert)
  8. ARM+llinux系统移植3G拨号上网收发短信(一)【转】
  9. [LeetCode] LRU Cache [Forward]
  10. csdn 去除广告