bzoj1139:[POI2009]Wie

传送门

状压dp,最短路
spfa似乎特别慢
代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
void read(int &x) {
    char ch; bool ok;
    for(ok=0,ch=getchar(); !isdigit(ch); ch=getchar()) if(ch=='-') ok=1;
    for(x=0; isdigit(ch); x=x*10+ch-'0',ch=getchar()); if(ok) x=-x;
}
#define rg register
const int maxn=210,maxm=3010;
int n,m,p,k,cnt,pre[maxm*2],nxt[maxm*2],h[maxn],v[maxm*2],vv[maxm*2],tj[maxn],f[maxn][1<<13],tot,ans=1e9;bool vis[maxn];
void add(int x,int y,int z,int zz)
{
	pre[++cnt]=y,nxt[cnt]=h[x],h[x]=cnt,v[cnt]=z,vv[cnt]=zz;
	pre[++cnt]=x,nxt[cnt]=h[y],h[y]=cnt,v[cnt]=z,vv[cnt]=zz;
}
queue<int>q;
void spfa(int x)
{
	q.push(x);
	while(!q.empty())
	{
		int y=q.front();q.pop();vis[y]=0;
		for(rg int i=h[y];i;i=nxt[i])
			for(rg int j=0;j<tot;j++)
				if((j&vv[i])==vv[i]&&f[pre[i]][j|tj[pre[i]]]>f[y][j]+v[i])
				{
					f[pre[i]][j|tj[pre[i]]]=f[y][j]+v[i];
					if(pre[i]==n){ans=min(ans,f[pre[i]][j|tj[pre[i]]]);continue;}
					if(!vis[pre[i]])vis[pre[i]]=1,q.push(pre[i]);
				}
	}
}
int main()
{
    read(n),read(m),read(p),read(k);
    memset(f,63,sizeof f);
    for(rg int i=1,q,t;i<=k;i++)
    {
    	read(q),read(t);
    	for(rg int j=1,x;j<=t;j++)read(x),tj[q]|=1<<(x-1);
    }
    for(rg int i=1,x,y,z,t,w;i<=m;i++)
    {
    	read(x),read(y),read(z),read(t),w=0;
    	for(rg int j=1,v;j<=t;j++)read(v),w|=1<<(v-1);
    	add(x,y,z,w);
    }
    tot=1<<p,f[1][tj[1]]=0;
    spfa(1);if(1==n)ans=0;
    printf("%d\n",ans>=1e9?-1:ans);
}
posted @ 2019-02-21 20:36  蒟蒻--lichenxi  阅读(130)  评论(0编辑  收藏  举报