zoukankan      html  css  js  c++  java
  • P2761 软件补丁问题

    状态压缩+dij 最短路


    考虑建图,由于 (n,m) 较小,所以可以把所有当前含有的错误用二进制的形式压在一个 int
    然后把这个数当作我们图中的节点

    其实建图的时候不用真正的连边,在跑 dij 的时候枚举每一个补丁,按照题意判断它能不能用,再计算出使用完后的错误集合,也就是一条边的终点
    用一点简单的位运算就可以了

    然后这个题还混入了网络瘤24题?

    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    #include<cmath>
    #include<map>
    #include<iomanip>
    #include<cstring>
    #define reg register
    #define EN std::puts("")
    #define LL long long
    inline int read(){
    	register int x=0;register int y=1;
    	register char c=std::getchar();
    	while(c<'0'||c>'9'){if(c=='-') y=0;c=std::getchar();}
    	while(c>='0'&&c<='9'){x=x*10+(c^48);c=std::getchar();}
    	return y?x:-x;
    }
    int n,m;
    int timee[106];
    int f1[106],f2[105],b1[106],b2[106];
    int dis[1050005],heap[1050005],size;
    int in[1050005];
    inline void push(int x){
    	heap[++size]=x;
    	reg int i=size,fa;
    	while(i>1){
    		fa=i>>1;
    		if(dis[heap[fa]]<=dis[heap[i]]) return;
    		std::swap(heap[fa],heap[i]);i=fa;
    	}
    }
    inline int pop(){
    	int ret=heap[1];heap[1]=heap[size--];
    	int i=1,ls,rs;
    	while((i<<1)<=size){
    		ls=i<<1;rs=ls|1;
    		if(rs<=size&&dis[heap[rs]]<dis[heap[ls]]) ls=rs;
    		if(dis[heap[ls]]>=dis[heap[i]]) break;
    		std::swap(heap[i],heap[ls]);i=ls;
    	}
    	return ret;
    }
    inline void get(int &x,int &y){
    	reg int i=0;
    	reg char c=std::getchar();
    	while(c!='0'&&c!='+'&&c!='-') c=std::getchar();
    	while(1){
    		i++;
    		if(c=='0');
    		else if(c=='+') x|=1<<(i-1);
    		else if(c=='-') y|=1<<(i-1);
    		else break;
    		c=std::getchar();
    	}
    }
    inline void dij(int s){
    	std::memset(dis,0x3f,sizeof dis);dis[s]=0;
    	push(s);in[s]=1;
    	reg int u,v;
    	while(size){
    		u=pop();in[u]=0;
    		for(reg int i=1;i<=m;i++)if(((u&b1[i])==b1[i])&&!(u&b2[i])){
    			v=(u&(~f1[i]))|f2[i];
    			if(dis[v]>dis[u]+timee[i]){
    				dis[v]=dis[u]+timee[i];
    				if(!in[v]) push(v),in[v]=1;
    			}
    		}
    //		else std::printf("no! u=%d id=%d , for b1 : %d , for b2 : %d
    ",u,i,((u&b1[i])==b1[i]),!(u&b2[i]));
    	}
    }
    int main(){
    	n=read();m=read();
    	for(reg int i=1;i<=m;i++){
    		timee[i]=read();
    		get(b1[i],b2[i]);get(f2[i],f1[i]);
    	}
    	dij((1<<n)-1);
    	std::printf("%d",dis[0]==0x3f3f3f3f?0:dis[0]);
    	return 0;
    }
    
  • 相关阅读:
    关于博客
    latex句首缩进空格
    javable 之Iterable
    javable之Comparable
    常量池与Integer和String的“==”
    静态多态与动态多态
    String和StringBuilder效率不同的原理
    equals和hashcode
    Eclipse里面使用checkstyle(Google style)
    矩阵链乘问题
  • 原文地址:https://www.cnblogs.com/suxxsfe/p/12704963.html
Copyright © 2011-2022 走看看