P3489 [POI2009]WIE-Hexer
阿新 • • 發佈:2020-07-25
P3489:https://www.luogu.com.cn/problem/P3489
bzoj1139:https://darkbzoj.tk/problem/1139
dij 分層圖最短路+狀態壓縮,把狀態大小上限 \(2^p-1\) 寫成了 \(2^{p-1}-1\),然後debug了將近一晚上。。。
由於 \(p\le 13\),而且當前能走哪些路不能走哪些,又和每一個劍的有無有關,所以我們用一個 13 為二進位制數來表示當前狀態下,每一個劍有沒有
\(dis_{i,S}\) 表示的就是從 \(1\) 到 \(i\),且狀態為 \(S\) 所需的最短路程
答案就是 \(\min\{dis_{n,S},S< 2^p\}\)
這裡為了 dij 那裡處理起來方便
id
陣列
然後 dij 中的每當開始處理一個 \(u\),就用當前節點鐵匠的資訊,來更新 \(S\),枚舉出邊的時候在判斷一下當前這條邊能不能走就行了
應該還是挺簡單
話說這題是當時剛學 dij 的時候,連堆優化都還不會,就用 dij 的標籤搜進了這題,然後還碼了半天,發現思路不對就直接讓它進任務計劃吃灰了
然後這一年多以後才想起來回來做
#include<cstdio> #include<algorithm> #include<iostream> #include<cmath> #include<queue> #include<iomanip> #include<cstring> #define reg register #define EN std::puts("") #define LL long long inline int read(){ register int x=0;register int y=1; register char c=std::getchar(); while(c<'0'||c>'9'){if(c=='-') y=0;c=std::getchar();} while(c>='0'&&c<='9'){x=x*10+(c^48);c=std::getchar();} return y?x:-x; } #define N 1700005 #define M 6005 struct graph{ int fir[N],nex[M],to[M],w[M],tot; inline void add(int u,int v,int z){ to[++tot]=v;w[tot]=z; nex[tot]=fir[u];fir[u]=tot; } }G; int n,m,p,k; int heap[N],size; int dis[N],in[N]; int blacksmith[N],monster[M]; int id[205][9005]; int get_i[N],get_S[N]; inline void push(int x){ heap[++size]=x; reg int i=size,fa; while(i>1){ fa=i>>1; if(dis[heap[fa]]<=dis[heap[i]]) return; std::swap(heap[fa],heap[i]);i=fa; } } inline int pop(){ int ret=heap[1];heap[1]=heap[size--]; reg int i=1,ls,rs; while((i<<1)<=size){ ls=i<<1;rs=ls|1; if(rs<=size&&dis[heap[rs]]<dis[heap[ls]]) ls=rs; if(dis[heap[i]]<=dis[heap[ls]]) break; std::swap(heap[ls],heap[i]);i=ls; } return ret; } inline void dij(){ std::memset(dis,0x3f,sizeof dis);dis[id[1][blacksmith[1]]]=0; push(id[1][blacksmith[1]]);in[id[1][blacksmith[1]]]=1; reg int u,v,S; while(size){ u=pop();in[u]=0; S=get_S[u]; S|=blacksmith[get_i[u]];//能打造新的劍就一定造 for(reg int i=G.fir[get_i[u]];i;i=G.nex[i]){ if((S&monster[i])!=monster[i]) continue; v=id[G.to[i]][S]; // printf("(%d %d)=> (%d %d)\n",u,v,get_i[u],get_i[v]); if(dis[v]>dis[u]+G.w[i]){ dis[v]=dis[u]+G.w[i]; if(!in[v]) push(v),in[v]=1; } } } } int main(){ n=read();m=read();p=read();k=read(); for(reg int w,num,i=1;i<=k;i++){ w=read();num=read(); while(num--) blacksmith[w]|=(1<<(read()-1)); } for(reg int i=1,u,v,w,num;i<=m;i++){ u=read();v=read();w=read();num=read(); G.add(u,v,w);G.add(v,u,w); while(num--){ u=read(); monster[G.tot]|=(1<<(u-1)); monster[G.tot-1]|=(1<<(u-1)); } } int id_=0; for(reg int i=1;i<=n;i++) for(reg int S=0;S<(1<<p);S++) id[i][S]=++id_,get_i[id_]=i,get_S[id_]=S; dij(); int ans=1e9; for(reg int S=0;S<(1<<p);S++) ans=std::min(ans,dis[id[n][S]]); printf("%d",ans==1e9?-1:ans); return 0; }