这题虽然是网络流24题中的,但是做完发现是一个可以多次经过一个点的SPFA算法(也就是变种啦)。
#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <cstring>
using namespace std ;
const int oo=1000000000;
int n,m;
typedef struct CODE{
int b1,b2;
int f1,f2;
int times;
CODE (){
b1=b2=f1=f2=0;
}
}C;
C a[110];
int dist[1<<21],q[100001],inq[1<<21];
int S,T;
void init (){
freopen ("prog812.in","r",stdin);
freopen ("prog812.out","w",stdout);
cin >>n >>m;
S=(1<<n)-1;
T=0;
int i,j;
char k;
for (i=1;i<=m;i++){
scanf ("%d ",&j);
a[i].times=j;
j=-1;
while (1){
scanf ("%c",&k);
if (k==' ') continue;
if (k=='\n') break;
j++;
if (j<n){
if (k=='-') a[i].b2|=(1<<j);
if (k=='+') a[i].b1|=(1<<j);
}
else {
if (k=='+') a[i].f2|=(1<<(j-n));
if (k=='-') a[i].f1|=(1<<(j-n));
}
}
}
}
bool check (int now,int id){
if((now | a[id].b1) != now) return false;
if(now & a[id].b2) return false;
return true;
}
void spfa (){
int now,i,next;
int head=0,tail=0;
for (i=0;i<=S;i++) dist[i]=oo;
q[tail++]=S;
dist[S]=0;
inq[S]=1;
while (head!=tail){
now=q[head++];
inq[now]=0;
if (head==100000) head=0;
for (i=1;i<=m;i++){
if (check (now,i)) {
next=(now & (~a[i].f1)) | a[i].f2;
if (dist[next]>dist[now]+a[i].times){
dist[next]=dist[now]+a[i].times;
if (!inq[next]){
q[tail++]=next;
if (tail==100000) tail=0;
inq[next]=1;
}
}
}
}
}
if (dist[T]==oo) printf ("0\n");
else printf ("%d\n",dist[T]);
}
int main (){
init ();
spfa ();
return 0;
}