洛谷 P2761 软件补丁问题 【spfa】

…为什么最短路的题会出现在网络流24里??

因为范围是15所以直接把每个状态作为一个点,向它能转移到的点连有向边即可。可以不用建图(据说建图存不下?),直接枚举m个转移方案。位运算比较麻烦注意不要写错。

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const int N=1500005,inf=1e9;
int n,m,dis[N];
char c1[N],c2[N];
struct qwe
{
    int y,n,d,a,c;
}e[N];
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%s%s",&e[i].c,c1,c2);
        for(int j=0;j<n;j++)
        {
            if(c1[j]==‘+‘)
                e[i].y^=(1<<(n-j-1));
            if(c1[j]==‘-‘)
                e[i].n^=(1<<(n-j-1));
            if(c2[j]==‘+‘)
                e[i].a^=(1<<(n-j-1));
            if(c2[j]==‘-‘)
                e[i].d^=(1<<(n-j-1));
        }
    }
    int s=(1<<n)-1,t=0;
    queue<int>q;
    for(int i=t;i<=s;i++)
        dis[i]=inf;
    dis[s]=0;
    q.push(s);
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        for(int i=1;i<=m;i++)
            if((u&e[i].n)==0&&(u&e[i].y)==e[i].y)
            {
                int now=((u|e[i].d)^e[i].d)|e[i].a;
                if(dis[now]>dis[u]+e[i].c)
                {
                    dis[now]=dis[u]+e[i].c;
                    q.push(now);
                }
            }
    }
    printf("%d\n",dis[t]==inf?0:dis[t]);
    return 0;
}

原文地址:https://www.cnblogs.com/lokiii/p/8421467.html

时间: 2024-10-09 03:11:57

洛谷 P2761 软件补丁问题 【spfa】的相关文章

P2761 软件补丁问题

P2761 软件补丁问题 思路 貌似不用网络流,直接状态压缩 用spfa跑最短路,直接判断是否能过 位运算太渣了,WA了好几发 代码 #include <bits/stdc++.h> using namespace std; const int N = 21, M = 101, inf = 0x3f3f3f3f; int read() { int x = 0, f = 1; char s = getchar(); for(; s > '9' || s < '0'; s = getc

[Luogu P2761] 软件补丁问题

Description T 公司发现其研制的一个软件中有 n 个错误,随即为该软件发放了一批共 m 个补丁程序.每一个补丁程序都有其特定的适用环境,某个补丁只有在软件中包含某些错误而同时又不包含另一些错误时才可以使用.一个补丁在排除某些错误的同时,往往会加入另一些错误. 换句话说,对于每一个补丁 i,都有 2 个与之相应的错误集合 B1[i]和 B2[i],使得仅当软件包含 B1[i]中的所有错误,而不包含 B2[i]中的任何错误时,才可以使用补丁 i.补丁 i 将修复软件中的某些错误 F1[i

[模板]洛谷T3371 单源最短路径 SPFA+手工队列类

一年之后又重新学习此算法...233... 1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<cmath> 5 #include<ctime> 6 #include<cstdlib> 7 8 #include<string> 9 #include<stack> 10 //#include<queue> 11

P2761 软件补丁问题 【状压】【最短路】

输入输出样例 输入 #1复制 3 3 1 000 00- 1 00- 0-+ 2 0-- -++ 输出 #1复制 8 思路 为啥会有网络流的tag wa了5发感觉怎么建图都不对 一看都是状压最短路 打了个dijRE了 发现好像边太多 看别人都用的spfa莽,干脆我也莽一发好了 大家都知道spfa的核心就是边建图边松弛 如何建图: 因为对于第 i 个错误来说,只存在‘待修复’和‘已修复’两种状态 为了方便枚举,对状态进行压缩成一个整数来枚举 因为可能成环,显然状压dp很难处理这类问题 考虑用spf

软件补丁问题(SPFA+位运算)

洛谷P2761 1.考虑到所有的错误只有"修复,未修复"两种情况,所以可以用0,1标记压缩状态,采用位运算减少时空浪费. 又考虑到有修复时间的关系,将时间抽象成边,将状态抽象为点(设修复为0,未修复为1)最后从(1<<n)-1开始寻找到0的最短路,SPFA一边建图一边松弛即可. 2.实现过程中,难点在于对二进制表示,以及位运算组合判断的处理. 首先,状态要表示(见前): 其次,补丁b,f要表示. 最初考虑用两个数来表示b,f,发现受"不动错误"影响,无法

洛谷P1144 最短路计数(SPFA)

To 洛谷.1144 最短路计数 题目描述 给出一个N个顶点M条边的无向无权图,顶点编号为1-N.问从顶点1开始,到其他每个点的最短路有几条. 输入输出格式 输入格式: 输入第一行包含2个正整数N,M,为图的顶点数与边数. 接下来M行,每行两个正整数x, y,表示有一条顶点x连向顶点y的边,请注意可能有自环与重边. 输出格式: 输出包括N行,每行一个非负整数,第i行输出从顶点1到顶点i有多少条不同的最短路,由于答案有可能会很大,你只需要输出mod 100003后的结果即可.如果无法到达顶点i则输

洛谷P1462 通往奥格瑞玛的道路 二分答案+最短路SPFA

洛谷P1462 通往奥格瑞玛的道路二分答案+最短路SPFA 二分交费最多的一次的钱数 然后只将符合要求的边加入图中 如果到终点的最短路大于等于血量 或者直接起点不能到达终点那么说明不符合要求 需要加大答案 时间复杂度 (log答案)* Ek 需要注意如果本来就不能到达 那么直接输出AFK 1 #include <bits/stdc++.h> 2 #define LL long long 3 #define For(i,j,k) for(int i=j;i<=k;i++) 4 using

缩点(洛谷3387)——不会写DP 的我只好来了个SPFA

我刚开始也不知道为什么就想到肯定是缩了点后把一个新点(原图中的强连通分量)的权值赋为它所含的所有点的权值之和,没有想着去推,纯粹是题目的名字启发我这么去干的……之后用SPFA 求最大路径,然而我连的全是无向边,导致答案错误了四个点,发现错误后觉得,之前的代码居然还对了六个点才是最让人震惊的. 1 #include<queue> 2 #include<stack> 3 #include<vector> 4 #include<iostream> 5 #inclu

洛谷P3385 【模板】负环 DFS-SPFA 判负环 图论

洛谷P3385 [模板]负环 图论 今天get了 一个 DFS-SPFA 判负环的方法 一般的 BFS-SPFA 判负环 一般就是 不停地做,如果某点第 n+1次加入队列中,那么说明这个图存在负环然而我并不会证明,期望复杂度是 O(kM) k 大约是在 2 左右 但是其实对于一些极限数据,最坏可以把他卡到 O( NM) 额,这就直接炸飞了是不是,而且据说,一些数据比较强的题目,总会想到卡一卡SPFA的, 然后我们换一种思路 因为题目中一定存在一种 负环对吧,所以说假如你某段路径权值和为自然数的时