當前位置:
首頁 >
前端技术
> javascript
>内容正文
javascript
P6085-[JSOI2013]吃货JYY【状压dp,欧拉回路】
生活随笔
收集整理的這篇文章主要介紹了
P6085-[JSOI2013]吃货JYY【状压dp,欧拉回路】
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
正題
題目鏈接:https://www.luogu.com.cn/problem/P6085
題目大意
nnn個點的一張無向圖,有kkk條必走邊,mmm條其他邊,求從111出發經過必走邊后回到起點的最短路徑。
2≤n≤13,0≤k≤78,2≤m≤2002\leq n\leq 13,0\leq k\leq 78,2\leq m\leq 2002≤n≤13,0≤k≤78,2≤m≤200
解題思路
可以理解為在只包含必走邊的圖上加若干條其他邊使得這張圖存在歐拉回路。
歐拉回路要求所有點聯通且度數為偶數,考慮狀態壓縮dpdpdp,設三進制的狀態。
fsf_sfs?,000表示沒有聯通,111表示度數為奇數,222表示度數為偶數。
然后先考慮加點進來的方式,也就是加進來的點我們只考慮不是必須的邊的部分。而且使用這些點類似于一棵樹的連接聯通的點。(并不是連接成真正的樹,而是如果使用了不必須的邊的話只和一個點聯通)
然后處理完后再考慮調整圖的奇偶性,設gSg_SgS?表示集合SSS中的點為奇數時調整為偶數的最小代價。
然后用fff和ggg計算答案就好了。
時間復雜度O(3nn2)O(3^nn^2)O(3nn2)
code
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> using namespace std; const int N=14; struct node{int to,next; }a[N*N]; int n,k,m,tot,ans,sta,st,ls[N],p[N],deg[N]; int dis[N][N],g[1<<N],f[1594323]; queue<int> q; void addl(int x,int y){a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot;return; } int main() {memset(dis,0x3f,sizeof(dis));memset(g,0x3f,sizeof(g));memset(f,0x3f,sizeof(f));scanf("%d%d",&n,&k);p[0]=1;dis[0][0]=0;for(int i=1;i<=n;i++)p[i]=p[i-1]*3,dis[i][i]=0;for(int i=1;i<=k;i++){int x,y,w;scanf("%d%d%d",&x,&y,&w);x--;y--;addl(x,y);addl(y,x);dis[x][y]=dis[y][x]=min(dis[x][y],w);deg[x]++;deg[y]++;sta^=(1<<x)^(1<<y);ans+=w;}scanf("%d",&m);for(int i=1;i<=m;i++){int x,y,w;scanf("%d%d%d",&x,&y,&w);x--;y--;dis[x][y]=dis[y][x]=min(dis[x][y],w);}for(int k=0;k<n;k++)for(int i=0;i<n;i++)for(int j=0;j<n;j++)dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);int MS=(1<<n);g[0]=0;for(int s=0;s<MS;s++)for(int i=0;i<n;i++){if((s>>i)&1)continue;for(int j=i+1;j<n;j++)if(!((s>>j)&1)){int z=s^(1<<i)^(1<<j);g[z]=min(g[z],g[s]+dis[i][j]);}}q.push(2);f[2]=0;while(!q.empty()){int s=q.front();q.pop();for(int x=0;x<n;x++){if(s/p[x]%3)continue;int t=s+p[x]*2;for(int i=ls[x];i;i=a[i].next){int y=a[i].to;if(!(s/p[y]%3))continue;if(f[t]>=g[MS])q.push(t);f[t]=min(f[t],f[s]);}for(int y=0;y<n;y++){if(!(s/p[y]%3))continue;t=s+p[x];if((t/p[y]%3)==2)t-=p[y];else t+=p[y];if(f[t]>=g[MS])q.push(t);f[t]=min(f[t],f[s]+dis[x][y]);}}}int mins=g[MS];for(int s=0;s<p[n];s++){bool flag=0;int st=0;for(int i=0;i<n;i++){if((s/p[i]%3)==0&°[i]){flag=1;break;}if(s/p[i]%3)st|=(1<<i)*(2-s/p[i]%3);}if(flag)continue;st^=sta;mins=min(mins,f[s]+g[st]);}printf("%d\n",ans+mins);return 0; }總結
以上是生活随笔為你收集整理的P6085-[JSOI2013]吃货JYY【状压dp,欧拉回路】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 汪星人是指什么样的人
- 下一篇: splay/fhq-treap 问卷调查