BZOJ1097: [POI2007]旅游景点atr
突然很想做POI。。
$n \leq 20000,m \leq 200000$的无向边权图无自环重边,问:从1出发到$n$,必须经过$2,3,...,k+1$,$k \leq 20$,且满足$q$个限制:在访问$x$后一定要访问$y$,$x,y<=k+1$,这样的最短路。
听说卡时间。我:????
看到$k \leq 20$明显状压一下(套路症晚期),$f(i,j)$,状态$i$,最后在位置$j$。转移时加上距离,对每个点记录他所有必须先访问的节点的二进制状态,和当前状态$and$一下判断可行。
然后$k$次最短路预处理一下距离即可。
1 #include<stdio.h> 2 #include<string.h> 3 #include<queue> 4 #include<stdlib.h> 5 #include<algorithm> 6 //#include<iostream> 7 using namespace std; 8 9 #define LL long long 10 int qread() 11 { 12 char c; int s=0,t=1; while ((c=getchar())<'0' || c>'9') (c=='-') && (t=-1); 13 do s=s*10+c-'0'; while ((c=getchar())>='0' && c<='9'); return s*t; 14 } 15 16 //Pay attention to LL and double of qread!!!! 17 18 int n,m,K,lq; 19 #define maxn 20011 20 #define maxm 400011 21 #define maxs 1111111 22 struct Edge{int to,v,next;}edge[maxm]; int first[maxn],le=2; 23 void in(int x,int y,int v) {Edge &e=edge[le]; e.to=y; e.v=v; e.next=first[x]; first[x]=le++;} 24 void insert(int x,int y,int v) {in(x,y,v); in(y,x,v);} 25 26 struct qnode 27 { 28 int v,id; 29 bool operator < (const qnode &b) const {return v>b.v;} 30 }; 31 priority_queue<qnode> q; 32 int ddd[maxn],dis[25][25]; 33 void dijkstra(int s) 34 { 35 for (int i=1;i<=n;i++) ddd[i]=0x3f3f3f3f; 36 ddd[s]=0; q.push((qnode){0,s}); 37 while (!q.empty()) 38 { 39 int x=q.top().id,d=q.top().v; q.pop(); 40 if (ddd[x]!=d) continue; 41 for (int i=first[x];i;i=edge[i].next) 42 { 43 Edge &e=edge[i]; 44 if (ddd[e.to]>ddd[x]+e.v) 45 { 46 ddd[e.to]=ddd[x]+e.v; 47 q.push((qnode){ddd[e.to],e.to}); 48 } 49 } 50 } 51 for (int i=1;i<=K+1;i++) dis[s][i]=ddd[i]; 52 dis[s][K+2]=ddd[n]; 53 } 54 55 int lim[233],f[maxs][20]; 56 int main() 57 { 58 n=qread(); m=qread(); K=qread(); 59 for (int i=1,x,y,v;i<=m;i++) 60 { 61 x=qread(); y=qread(); v=qread(); 62 insert(x,y,v); 63 } 64 lq=qread(); 65 for (int i=1,x,y;i<=lq;i++) 66 { 67 x=qread(); y=qread(); 68 lim[y]|=1<<(x-2); 69 } 70 // for (int i=2;i<=K+1;i++) cout<<lim[i]<<' ';cout<<endl; 71 72 for (int i=1;i<=K+1;i++) dijkstra(i); 73 if (K==0) {printf("%d\n",dis[1][2]); return 0;} 74 75 memset(f,0x3f,sizeof(f)); 76 for (int i=0;i<K;i++) if (lim[i+2]==0) f[1<<i][i]=dis[1][i+2]; 77 for (int i=1;i<(1<<K);i++) 78 { 79 // for (int j=0;j<K;j++) cout<<((i>>j)&1)<<' '; for (int j=0;j<K;j++) cout<<f[i][j]<<' ';cout<<endl; 80 for (int j=0;j<K;j++) if (((i>>j)&1)==0 && (i&lim[j+2])==lim[j+2]) 81 { 82 int ni=i|(1<<j); 83 for (int k=0;k<K;k++) f[ni][j]=min(f[ni][j],f[i][k]+dis[k+2][j+2]); 84 } 85 } 86 int ans=0x3f3f3f3f; 87 for (int i=0;i<K;i++) ans=min(ans,f[(1<<K)-1][i]+dis[i+2][K+2]); 88 printf("%d\n",ans); 89 return 0; 90 }
注意下$k=0$啊,WA到懵逼。