• 差分约束 + spfa + 最长路 [NOI1999] 01串


    https://blog.csdn.net/Bill_Yang_2016/article/details/53556021

    题目描述
      给定7个整数N,A0,B0,L0,A1,B1,L1,要求设计一个01串S=s1s2…si…sN,满足:
      1.si=0或si=1,1<=i<=N;
      2.对于S的任何连续的长度为L0的子串sjsj+1…sj+L0-1(1<=j<=N-L0+1),0的个数大于等于A0且小于等于B0;
      3.对于S的任何连续的长度为L1的子串sjsj+1…sj+L1-1(1<=j<=N-L1+1),1的个数大于等于A1且小于等于B1;
      例如,N=6,A0=1,B0=2,L0=3,A1=1,B1=1,L1=2,则存在一个满足上述所有条件的01串S=010101。

    用 S 表示01序列的1的个数的前缀和,然后就可以利用题目所给的不等式以及前缀和本身存在的信息,写出不等式进行差分约束算法。

    注意!用前缀和表示区间和的时候所使用的前缀和数组的 L 要减1 。

    #include <bits/stdc++.h>
    using namespace std;
    
    const int maxn = 1e5+110;
    int n,a0,b0,l0,a1,b1,l1;
    int s[maxn];
    int cnt;
    
    struct node{
        int from,to,val,next;
    }edge[maxn];
    int head[maxn];
    
    void add(int u,int v,int val){
        edge[cnt].from = u;
        edge[cnt].to = v;
        edge[cnt].val = val;
        edge[cnt].next = head[u];
        head[u] = cnt;
        cnt++;
    }
    
    int dis[maxn],vis[maxn],num[maxn];
    const int inf = 0x3f3f3f3f;
    
    bool spfa(){
        for(int i=0; i<=n; i++){
            dis[i] = 0;
            vis[i] = 0;
            dis[i] = inf;
            num[i] = 0;
        }
        dis[0] = 0;
        vis[0] = 1;
        num[0]++;
        queue<int> q;
        q.push(0);
        while(!q.empty()){
            int u = q.front();
            q.pop();
            vis[u] = 0;
            for(int i=head[u]; i; i=edge[i].next){
                int v = edge[i].to;
                int w = edge[i].val;
                if(dis[v] - dis[u] > w){
                    dis[v] = dis[u] + w;
                    if(!vis[v]){
                        num[v]++;
                        if(num[v] >= n) return false;
                        q.push(v);
                        vis[v] = 1;
                    }
                }
            }
        }
        return true;
    }
    
    int main(){
        int T=5;
        while(T--){
        cin>>n>>a0>>b0>>l0>>a1>>b1>>l1;
        dis[0] = 0;
        cnt = 1;
        memset(edge,0,sizeof(edge));
        memset(head,0,sizeof(head));
        for(int i=1; i<=n; i++){
            if(i+l0-1<=n){
                add(i-1,i+l0-1,-(l0-b0));      //注意!这个类似前缀和
                add(i+l0-1,i-1,-(-(l0-a0)));      //而前缀和计算区间内容时头要减1!!
            }
            if(i+l1-1<=n){
                add(i-1,i+l1-1,-a1);
                add(i+l1-1,i-1,-(-b1));
            }
                add(i-1,i,0);
                add(i,i-1,-(-1));
        }
        bool flag=spfa();
        if(flag==0) cout<<"-1"<<endl;
        else{
            for(int i=1; i<=n; i++){
                // cout<<dis[i]<<" ";
                if(dis[i]<dis[i-1])
                    cout<<'1';
                else
                    cout<<'0';
            }
            cout<<endl;
        }
        }
    }
  • 相关阅读:
    BZOJ 3531[Sdoi2014]旅行
    BZOJ4998 星球联盟
    BZOJ2959 长跑
    【北京集训D2T3】tvt
    [Bzoj]5343: [Ctsc2018]混合果汁
    HGOI20190810 省常中互测3
    HGOI20190809 省常中互测2
    HGOI20190808 省常中互测1
    组合排列和组合数 学习笔记
    2-SAT (two-statisfiability) 算法 学习笔记
  • 原文地址:https://www.cnblogs.com/-Zzz-/p/11938665.html
Copyright © 2020-2023  润新知