您的位置:首页 > 理论基础 > 计算机网络

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

2017-08-27 19:50 295 查看

传送门

软件补丁

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

I think

实质上是一个最短路问题,同UVA658.

用二进制串表示软件的漏洞状态,1表示存在漏洞,0表示不存在漏洞.答案即是从状态1…11(共有n个1)->0…00的最短路.

若提前建图会直接有2^n个点,边更多,不仅存储麻烦而且许多状态完全不会出现在最短路里.因此一边跑最短路一边建图(判断当前状态是否能够使用补丁,使用补丁后连边向怎样的状态).

Code

#include<cstdio>
#include<queue>

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<state> 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<<N)-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<<N)-1);
if(Ans==Inf) puts("0");
else printf("%d\n",Ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: