BZOJ4479 : [Jsoi2013]吃貨jyy

來源:互聯網
上載者:User

標籤:printf   return   dijkstra   最壞情況   歐拉迴路   empty   ext   class   highlight   

若$k\leq 15$,那麼可以設$d[i][S]$表示經過了$S$集合的邊,現在位於$i$點的最短路。

可以用Dijkstra演算法在$O(n^22^k)$時間內求出。

否則若$k>15$,那麼最壞情況下,它們會形成一個團,將這$k$條邊連上後,圖中最多剩下$7$個連通塊。

如果知道哪些邊要走,哪些邊不走的話,那麼只要存在歐拉迴路就可以。

也就是說,所有點的度數都是偶數,且從$1$出發可以到達$k$條邊的端點。

於是考慮DP,設$f[i][j][k]$表示考慮前$i$條邊,目前連通性為$j$,每個點度數的奇偶性為$k$的最小代價。

時間複雜度$O(n^2Bell(7)2^n)$,狀態比較稀疏,可以通過。

 

#include<cstdio>#include<queue>#include<vector>#include<algorithm>#include<map>using namespace std;typedef pair<int,int>P;typedef pair<int,P>PI;typedef long long ll;const int N=13,M=880,inf=100000000,LIM=15;int n,m,K,o,i,j,k,x,y,z;inline void up(int&a,int b){a>b?(a=b):0;}namespace SMALL{int f[N][N][2],g[N][N],d[N][1<<LIM];priority_queue<PI,vector<PI>,greater<PI> >q;inline void ext(int x,int y,int z){  if(d[x][y]<=z)return;  q.push(PI(d[x][y]=z,P(x,y)));}void solve(){  for(i=0;i<n;i++)for(j=0;j<n;j++)f[i][j][0]=-1;  for(i=0;i<n;i++)for(j=0;j<n;j++)g[i][j]=inf;  for(i=0;i<K;i++){    scanf("%d%d%d",&x,&y,&z);x--,y--;    f[x][y][0]=f[y][x][0]=i;    f[x][y][1]=f[y][x][1]=z;  }  scanf("%d",&m);  while(m--){    scanf("%d%d%d",&x,&y,&z);x--,y--;    up(g[x][y],z),up(g[y][x],z);  }  for(i=0;i<n;i++)for(j=0;j<1<<K;j++)d[i][j]=inf;  ext(0,0,0);  while(!q.empty()){    PI t=q.top();q.pop();    x=t.second.first,y=t.second.second,z=t.first;    if(z>d[x][y])continue;    for(i=0;i<n;i++){      if(~f[x][i][0])ext(i,y|(1<<f[x][i][0]),z+f[x][i][1]);      ext(i,y,z+g[x][i]);    }  }  printf("%d",d[0][(1<<K)-1]);}}namespace BIG{bool must[N];int a[N],h,t,e[N][N],dp[2][1<<N],g[M][N][N],ans=inf;int w[2][M][1<<N];char T,v[2][M][1<<N];short s[2][M][1<<N],cnt[2][M];ll q[M];map<ll,int>id;inline void merge(int x,int y){  x=a[x],y=a[y];  for(int i=0;i<n;i++)if(a[i]==x)a[i]=y;}inline ll encode(){  int i,m=0;ll t=0;  static int v[N];  for(i=0;i<n;i++)v[a[i]]=-1;  for(i=0;i<n;i++){    if(v[a[i]]<0)v[a[i]]=m++;    t=t<<4|v[a[i]];  }  return t;}inline void decode(ll f){for(int i=n-1;~i;i--)a[i]=f&15,f>>=4;}inline bool check(ll f){  decode(f);  for(int i=0;i<n;i++)if(must[i]&&a[i]!=a[0])return 0;  return 1;}inline int ext(ll x){  int&o=id[x];  if(o)return o;  q[o=++t]=x;  return o;}inline void clr(){  T++;  for(int i=1;i<=t;i++)cnt[o^1][i]=0;}inline void add(int x,int y,int z){  if(z>=inf)return;  if(v[o^1][x][y]<T){    v[o^1][x][y]=T;    w[o^1][x][y]=z;    s[o^1][x][cnt[o^1][x]++]=y;    return;  }  up(w[o^1][x][y],z);}void solve(){  for(i=0;i<n;i++)a[i]=i;  for(i=1;i<1<<n;i++)dp[0][i]=inf;  while(K--){    scanf("%d%d%d",&x,&y,&z);x--,y--;    must[x]=must[y]=1;    merge(x,y);    for(i=0;i<1<<n;i++)dp[o^1][i]=inf;    for(i=0;i<1<<n;i++)if(dp[o][i]<inf){      up(dp[o^1][i^(1<<x)^(1<<y)],dp[o][i]+z);      up(dp[o^1][i],dp[o][i]+z+z);    }    o^=1;  }  decode(encode());  h=1;  ext(encode());  while(h<=t){    ll x=q[h];    for(i=0;i<n;i++)for(j=0;j<n;j++){      decode(x);      merge(i,j);      g[h][i][j]=ext(encode());    }    h++;  }  scanf("%d",&m);  for(i=0;i<n;i++)for(j=0;j<n;j++)e[i][j]=inf;  while(m--){    scanf("%d%d%d",&x,&y,&z);x--,y--;    if(x==y)continue;    if(x>y)swap(x,y);    up(e[x][y],z);  }  clr();  for(i=0;i<1<<n;i++)add(1,i,dp[o][i]);  o^=1;  for(x=0;x<n;x++)for(y=0;y<n;y++)if(e[x][y]<inf){    z=e[x][y];    clr();    for(i=1;i<=t;i++)for(j=0;j<cnt[o][i];j++){      int S=s[o][i][j],f=w[o][i][S];      add(i,S,f);      add(g[i][x][y],S^(1<<x)^(1<<y),f+z);      add(g[i][x][y],S,f+z+z);    }    o^=1;  }  for(i=1;i<=t;i++)if(check(q[i]))for(j=0;j<cnt[o][i];j++)if(!s[o][i][j])up(ans,w[o][i][0]);  printf("%d",ans);}}int main(){  scanf("%d%d",&n,&K);  if(!K)return puts("0"),0;  if(K<=LIM)SMALL::solve();else BIG::solve();  return 0;}

  

BZOJ4479 : [Jsoi2013]吃貨jyy

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

Tags Index: