UESTC 1646 穷且益坚, 不坠青云之志。 差分约束、Fellman-ford

来源:互联网 发布:淘宝升钻有什么好处 编辑:程序博客网 时间:2024/06/07 05:53

穷且益坚, 不坠青云之志。

Time Limit: 6000/2000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)


Submit  Status
求一个有n个元素的数列,满足任意连续p个数的和不小于s,任意连续q个数的和不大于t。


Input

输入包括五个数n,p,q,s,t(1≤n,p,q≤500,1≤s,t≤100000)


Output

如果不能做到,输出"No"


否则输出"Yes",并在第二行输出一个可行解,包括n个数,保证在int范围内有解。


Sample input and output

Sample Input Sample Output
4 2 2 1 2                      Yes

                                      1 0 1 0



Source

2017 UESTC Training for Graph Theory

UESTC 1646 穷且益坚, 不坠青云之志。  


My Solution

题意:求一个有n个元素的数列,满足任意连续p个数的和不小于s,任意连续q个数的和不大于t。


差分约束、Fellman-ford
令sum[i]表示前i项的和(0<=i<=n,sum[0]=0)
那么题目的条件可转化为:
sum[i]-sum[i-p]>=s (p<=i<=n)
sum[i]-sum[i-q]<=t (q<=i<=n)
将第一个不等式取反,得到
sum[i-p]-sum[i]<=-s(p<=i<=n)
于是问题转化为求一系列不等式的解,这是一个典型的差分约束问题。


考虑最短路径的性质,令dis[i]表示从s到i的最短路,则对于图中存在的一条边(u,v),
有dis[v]<=dis[u]+w(u,v),即dis[v]-dis[u]<=w(u,v);
类比不等式,于是可建图,i向i-p引长度为-s的边,i-q向i引长度为t的边。

然后运行bellmanford,如果存在负环,则无解,
否则所得到的最短路的值就是sum[i]的一个解。

时间复杂度 O(VE)
空间复杂度 O(V + E)


#include <iostream>#include <cstdio>#include <queue>#include <vector>#include <cstring>using namespace std;typedef long long LL;typedef pair<int, LL> ii;const int MAXN = 1e3 + 8;const LL INF = 1e9;vector<ii> sons[MAXN];LL dis[MAXN];int cnt[MAXN];bool inque[MAXN];queue<int> que;//O(nlogn)inline bool SPFA(int n, int src){    for(int i = 0; i <= n; i++){        dis[i] = INF;    }    memset(inque, false, sizeof inque);    memset(cnt, 0, sizeof cnt);    dis[src] = 0;while(!que.empty()) que.pop();que.push(src);inque[src] = true;for(int i = 1; i <= n; i++){        que.push(i);        inque[i] = true;}//这样不连通也能跑Bellman-fordLL u, v, w, sz, i;while(!que.empty()){        u = que.front();        que.pop();        inque[u] = false;        sz = sons[u].size();for(i = 0; i < sz; i++){v = sons[u][i].first;w = sons[u][i].second;if(dis[u] + w < dis[v]){dis[v] = dis[u] + w;cnt[v]++;if(cnt[v] > n) return false;if(!inque[v]){                    inque[v] = true;                    que.push(v);}}}}return true;}int main(){    #ifdef LOCAL    freopen("j.txt", "r", stdin);    //freopen("j.out", "w", stdout);    int T = 1;    while(T--){    #endif // LOCAL    //ios::sync_with_stdio(false); cin.tie(0);    int n, p, q, i;    LL s, t;    scanf("%d%d%d%lld%lld", &n, &p, &q, &s, &t);    for(i = 0; i <= n; i++){        if(i - p >= 0) sons[i].push_back(ii(i-p, -s));        if(i - q >= 0) sons[i-q].push_back(ii(i, t));    }    if(!SPFA(n, 0)) puts("No");    else{        printf("Yes\n%lld", dis[1]);        for(i = 2; i <= n; i++){            printf(" %lld", dis[i] - dis[i-1]);        }        putchar('\n');    }    #ifdef LOCAL    cout << endl;    }    #endif // LOCAL    return 0;}



  Thank you!

                                                                                                                                            ------from ProLights

阅读全文
0 0
原创粉丝点击