javascript
P6085-[JSOI2013]吃货JYY【状压dp,欧拉回路】
正題
題目鏈接:https://www.luogu.com.cn/problem/P6085
題目大意
nnn個(gè)點(diǎn)的一張無向圖,有kkk條必走邊,mmm條其他邊,求從111出發(fā)經(jīng)過必走邊后回到起點(diǎn)的最短路徑。
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
解題思路
可以理解為在只包含必走邊的圖上加若干條其他邊使得這張圖存在歐拉回路。
歐拉回路要求所有點(diǎn)聯(lián)通且度數(shù)為偶數(shù),考慮狀態(tài)壓縮dpdpdp,設(shè)三進(jìn)制的狀態(tài)。
fsf_sfs?,000表示沒有聯(lián)通,111表示度數(shù)為奇數(shù),222表示度數(shù)為偶數(shù)。
然后先考慮加點(diǎn)進(jìn)來的方式,也就是加進(jìn)來的點(diǎn)我們只考慮不是必須的邊的部分。而且使用這些點(diǎn)類似于一棵樹的連接聯(lián)通的點(diǎn)。(并不是連接成真正的樹,而是如果使用了不必須的邊的話只和一個(gè)點(diǎn)聯(lián)通)
然后處理完后再考慮調(diào)整圖的奇偶性,設(shè)gSg_SgS?表示集合SSS中的點(diǎn)為奇數(shù)時(shí)調(diào)整為偶數(shù)的最小代價(jià)。
然后用fff和ggg計(jì)算答案就好了。
時(shí)間復(fù)雜度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; }總結(jié)
以上是生活随笔為你收集整理的P6085-[JSOI2013]吃货JYY【状压dp,欧拉回路】的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 汪星人是指什么样的人
- 下一篇: 单眼皮怎么画眼线 单眼皮画眼线 的步骤讲