bzoj 3055 禮物運送
阿新 • • 發佈:2019-02-11
首先處理出兩點之間最短路,設狀態f[i][j]表示j狀態下結尾為i的最短路,所以有轉移f[i][j]=f[k][j|(1<<(k-1))]+dis[i][k];
初狀態就是f[i][(1<<(i-1))]=dis[1][i],因為忽略了第一個點,在列舉的時候後面的點都要為i-2,具體看程式碼。
#include<cstdio> #include<cmath> #include<algorithm> #include<cstring> #include<queue> using namespace std; int n,m; int head[20],cnt=1; int used[20][20],dis[20][20]; int f[20][(1<<18)+5],dp[(1<<18)+5],tot=0x3f3f3f3f; struct node { int to,nxt,val; }edge[200005]; struct wee { int val,pos; }xz[20][20]; void init() { memset(head,-1,sizeof(head)); memset(dis,0x3f,sizeof(dis)); memset(dp,0x3f,sizeof(dp)); } void add(int from,int to,int val) { edge[cnt].to=to; edge[cnt].val=val; edge[cnt].nxt=head[from]; head[from]=cnt++; } int cmp(wee x,wee y) { return x.val<y.val; } queue<int>M; void spfa(int rt) { dis[rt][rt]=0; used[rt][rt]=1; M.push(rt); while(!M.empty()) { int u=M.front();M.pop(); for(int i=head[u];i!=-1;i=edge[i].nxt) { int to=edge[i].to; if(dis[rt][to]>dis[rt][u]+edge[i].val) { dis[rt][to]=dis[rt][u]+edge[i].val; if(used[rt][to])continue; M.push(to);used[rt][to]=1; } } used[rt][u]=0; } } int main() { scanf("%d%d",&n,&m);init(); for(int i=1;i<=m;i++) { int a,b,c; scanf("%d%d%d",&a,&b,&c); add(a,b,c);add(b,a,c); } for(int i=1;i<=n;i++)spfa(i); memset(f,0x3f,sizeof(f)); for(int i=2;i<=n;i++) { f[i][(1<<(i-2))]=dis[1][i]; } for(int j=0;j<=(1<<(n-1))-1;j++) { for(int i=2;i<=n;i++) { if(j&(1<<(i-2))) { for(int k=2;k<=n;k++) { if(!(j&(1<<(k-2)))) { f[k][j|(1<<(k-2))]=min(f[k][j|(1<<(k-2))],f[i][j]+dis[i][k]); } } } } } for(int i=0;i<=(1<<(n-1))-1;i++) { for(int j=2;j<=n;j++) { dp[i]=min(dp[i],f[j][i]); } } for(int i=0;i<=(1<<(n-1))-1;i++) { tot=min(tot,max(dp[i],dp[(1<<(n-1))-1-i])); } printf("%d",tot); return 0; }