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

和自甴很熟 提交于 2019-12-05 17:56:13

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;
    }
    }
}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!