BZOJ P1097 「POI2007」旅游景点atr【最短路】【状态压缩】

最短路预处理,然后普通的状压状态转移就好了:

#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define rep(i,x,y) for(int i=(x);i<=(y);i++)
#define repd(i,x,y) for(int i=(x);i>=(y);i--)
using namespace std;

const int Inf=1e9;
const int N=2e4+5;
const int M=2e5+5;

int f[22][1<<20];

int n,m,t,h,ans=Inf,lim[N],vis[N],dis[22][N];
int cnt,to[M<<1],edge[M<<1],nxt[M<<1],head[M];

inline int read() {
	int x=0;char ch=getchar();bool f=0;
	while(ch>'9'||ch<'0'){if(ch=='-')f=1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
	return f?-x:x;
}

void ins(int x,int y,int z) {
	to[++cnt]=y;edge[cnt]=z;nxt[cnt]=head[x];head[x]=cnt;
}

void spfa(int s) {
	rep(i,1,n) vis[i]=0,dis[s][i]=Inf;
	queue<int>q;q.push(s);vis[s]=1;dis[s][s]=0;
	
	while(q.size()) {
		int x=q.front();q.pop();vis[x]=0;
		
		for(int i=head[x];i;i=nxt[i]) {
			int y=to[i],z=edge[i];
			
			if(dis[s][x]+z<dis[s][y]) {
				dis[s][y]=dis[s][x]+z;
				if(!vis[y]) {
					vis[y]=1;q.push(y);
				}
			}
		}
	}
}

int dp(int cur,int s) {
	if(~f[cur][s]) return f[cur][s];
	
	if(s==h) return dis[cur][n];
	
	f[cur][s]=Inf;
	
	rep(i,2,t+1) if((s&lim[i])==lim[i]) f[cur][s]=min(f[cur][s],dis[cur][i]+dp(i,s|(1<<(i-2))));
	
	return f[cur][s];
}

int main() {
	memset(f,-1,sizeof(f));
	n=read(),m=read(),t=read();h=(1<<t)-1;
	
	rep(i,1,m) {
		int x=read(),y=read(),z=read();ins(x,y,z);ins(y,x,z);
	}
	
	rep(i,1,t+1) spfa(i);
	
	int limit=read();
	rep(i,1,limit) {
		int x=read(),y=read();lim[y]|=(1<<(x-2));
	}
	
	printf("%d",dp(1,0));
	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/yanzhenhuai/article/details/82813479