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);
}