网络流24题——软件补丁问题(spfa+位运算)

来源:互联网 发布:淘宝积分记录怎么删除 编辑:程序博客网 时间:2024/04/30 14:08

1.用unsigned int表示集合,与int分开

2.位运算100万个状态,这种状态之间是可以转移,有转移费用,求原点到终点的最短费用类似,直接最短路搞起

#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#include<iostream>#include<queue>#define debug(x) cout<<#x<<"="<<x<<endlusing namespace std;const int inf=0x3f3f3f3f;int n,m,cost[109];unsigned int b1[109],b2[109],f1[109],f2[109];//表示集合 int hs[1<<25];int dis[1<<21];bool b[1<<21];bool pan(int i,int n){if ((b1[i]|n)!=n) return false;if (b2[i]&n) return false;return true;}void dfs(int n){memset(dis,inf,sizeof(dis));memset(b,false,sizeof(b));queue<int> q;q.push(n);dis[n]=0;b[n]=true;while (!q.empty()){int u=q.front();q.pop();for (int i=1;i<=m;i++)if (pan(i,u)){int x=(u&(~f1[i]))|f2[i];if (dis[x]>dis[u]+cost[i]) {dis[x]=dis[u]+cost[i];if (!b[x]) b[x]=true,q.push(x);}}b[u]=false;}}int main(){scanf("%d%d",&n,&m);n=(1<<n)-1;char ch[109];for (int i=1;i<=m;i++){scanf("%d",&cost[i]);scanf("%s",ch);for (int j=0;j<strlen(ch);j++)if (ch[j]=='+') b1[i]+=(1<<j);else //need virusif (ch[j]=='-') b2[i]+=(1<<j); //not need virusscanf("%s",ch);for (int j=0;j<strlen(ch);j++)if (ch[j]=='+') f2[i]+=(1<<j);elseif (ch[j]=='-') f1[i]+=(1<<j);}dfs(n);if (dis[0]!=inf) printf("%d",dis[0]);else printf("0");return 0;}


0 0
原创粉丝点击