【网络流24题】软件补丁(最短路)

传送门

    软件补丁
    题意:给出若干个在特定条件下(修复前后有指定状态)适用的修复补丁,求利用给出补丁将一个有若干漏洞的软件修复为没有漏洞的软件的最小修复次数.

I think

    实质上是一个最短路问题,同UVA658.
    用二进制串表示软件的漏洞状态,1表示存在漏洞,0表示不存在漏洞.答案即是从状态1…11(共有n个1)->0…00的最短路.
    若提前建图会直接有2^n个点,边更多,不仅存储麻烦而且许多状态完全不会出现在最短路里.因此一边跑最短路一边建图(判断当前状态是否能够使用补丁,使用补丁后连边向怎样的状态).

Code

#include
#include

const int sm = 120;
const int sn = 1048576+20;
const int Inf = 0x3f3f3f3f;

int N,M,Ans;
bool vis[sn]; int d[sn];
struct patch {
    int c; char fm[30],to[30];
}P[sm];
struct state {
    int u,d;
    bool operator < (const state&a) const {
        return d>a.d;
    }
};
std::priority_queue Que;

int Judge(int x,patch y) {
    int loc = N-1,p=0;
    while(loc>=0) {
        if(y.to[loc]=='0'&&(x%2)) p+=1<<(N-1-loc);
        if(y.to[loc]=='+') p+=1<<(N-1-loc);

        if(y.fm[loc]=='-'&&(x%2)) return -1;
        if(y.fm[loc]=='+'&&(x%2==0)) return -1;
        x/=2, --loc;
    }
    return p;
}

int Dijkstra(int St) {
    for(int i=0;i<=(1<1;++i) 
        vis[i]=0,d[i]=Inf;
    state t;int tt; d[St]=0;
    Que.push((state){St,d[St]});
    while(!Que.empty()) {
        t=Que.top(),Que.pop();
        if(vis[t.u]) continue;
        vis[t.u]=1;
        for(int i=1;i<=M;++i) {
            tt=Judge(t.u,P[i]); 
            if(tt!=-1&&!vis[tt]&&d[tt]>d[t.u]+P[i].c) {
                d[tt]=d[t.u]+P[i].c;
                Que.push((state){tt,d[tt]});
            }
        }
    }
    return d[0];    
}   
int main() {
    scanf("%d%d",&N,&M);
    for(int i=1;i<=M;++i)
        scanf("%d%s%s",&P[i].c,P[i].fm,P[i].to);
    Ans=Dijkstra((1<1);
    if(Ans==Inf) puts("0");
    else printf("%d\n",Ans);
    return 0;
}

你可能感兴趣的:(最短路,网络流)