zoukankan      html  css  js  c++  java
  • [网络流24题]软件补丁问题

    分析

    裸的最短路:

    把错误集合状压成一个二进制,第i为为1表示有第i个错误

    把这个状态x作为图上的节点编号,dist[x]表示转移到状态x需要的时间

    显然初始状态为dist[(2^n-1)]最终的答案为dist[0]

    转移的时候枚举每一个补丁,通过位运算判断补丁i是否能修复当前状态

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #define maxm 1005
    #define maxn 1<<21 
    #define INF 0x3f3f3f3f
    using namespace std;
    int n,m;
    char s[maxm];
    int t[maxm];
    int b1[maxm],b2[maxm],f1[maxm],f2[maxm];
    
    int dist[maxn];
    int inq[maxn];
    int spfa(int s){
    	queue<int>q;
    	memset(dist,0x3f,sizeof(dist));
    	q.push(s);
    	dist[s]=0;
    	inq[s]=1;
    	while(!q.empty()){
    		int x=q.front();
    		q.pop();
    		inq[x]=0;
    		for(int i=1;i<=m;i++){//枚举每一个补丁
    			if((b1[i]|x)==x&&(b2[i]&x)==0){//x包括b1[i],不包括b2[i]
    				int y=x^(x&f1[i]);//x&f1[i]为x中能被修复的错误,再异或就相当于把错误去掉
    				y|=f2[i];//加上新增的错误
    				if(dist[y]>dist[x]+t[i]){
    					dist[y]=dist[x]+t[i];
    					if(!inq[y]){
    						q.push(y);
    						inq[y]=1;
    					}
    				}
    			}
    		}
    	}
    	if(dist[0]==INF) return 0;
    	else return dist[0];
    }
    int main(){
    	scanf("%d %d",&n,&m);
    	for(int i=1;i<=m;i++){
    		scanf("%d",&t[i]);
    		scanf("%s",s);
    		for(int j=0;j<n;j++){
    			if(s[j]=='+') b1[i]|=(1<<j);
    			else if(s[j]=='-') b2[i]|=(1<<j);
    		}
    		scanf("%s",s);
    		for(int j=0;j<n;j++){
    			if(s[j]=='-') f1[i]|=(1<<j);
    			else if(s[j]=='+') f2[i]|=(1<<j);
    		}
    	}
    	printf("%d
    ",spfa((1<<n)-1));
    } 
    
  • 相关阅读:
    区块链
    区块链
    区块链
    区块链
    区块链 – 介绍
    区块链 教程
    Matplotlib 直方图
    Matplotlib 饼图
    Matplotlib 柱状图
    Matplotlib 多个图形
  • 原文地址:https://www.cnblogs.com/birchtree/p/10602802.html
Copyright © 2011-2022 走看看