「网络流24题」 12. 软件补丁问题

「网络流24题」 12. 软件补丁问题

<题目链接>


状压 DP,SPFA 转移。

没错,跟网络流没任何关系。

b1、b2、f1、f2 都用二进制存下来,第 i 位表示是否有这个错误。

然后从每位都是 1 到 0 跑一个 SPFA 就好了。

#include <cstdio>
#include <cstring>
#include <queue>
using std::queue;
const int MAXN=1<<21,MAXM=110,INF=0x3f3f3f3f;
bool exist[MAXN];
int n,m,w[MAXM],b1[MAXM],b2[MAXM],f1[MAXM],f2[MAXM],dis[MAXN];
void Initialize(void)
{
	char s1[30],s2[30];
	for(int i=1;i<=m;++i)
	{
		scanf("\n%d%s%s",&w[i],s1,s2);
		for(int j=0,t;j<n;++j)
		{
			t=1<<j;
			if(s1[j]=='+')
				b1[i]|=t;
			else if(s1[j]=='-')
				b2[i]|=t;
			if(s2[j]=='-')
				f1[i]|=t;
			else if(s2[j]=='+')
				f2[i]|=t;
		}
	}
}
bool Skip(int i,int x)
{
	return (x|b1[i])^x || x&b2[i];
}
bool SPFA(int S,int T)
{
	queue<int> q;
	memset(dis,0x3f,sizeof dis);
	q.push(S);
	exist[S]=true;
	dis[S]=0;
	while(!q.empty())
	{
		int u=q.front();
		q.pop();
		exist[u]=false;
		for(int i=1,v;i<=m;++i)
			if(!Skip(i,u))
			{
				v=(u^(u&f1[i]))|f2[i];
				if(dis[v]>dis[u]+w[i])
				{
					if(!exist[v])
					{
						q.push(v);
						exist[v]=true;
					}
					dis[v]=dis[u]+w[i];
				}
			}
	}
	return dis[T]^INF;
}
int main(int argc,char** argv)
{
	scanf("%d %d",&n,&m);
	Initialize();
	printf("%d\n",SPFA((1<<n)-1,0) ? dis[0] : 0);
	return 0;
}

谢谢阅读。

posted @ 2018-06-03 15:00  Capella  阅读(182)  评论(0编辑  收藏  举报

谢谢光临