工程规划 --- 差分约束 + spfa (含自制lemon的spj)

传送门:洛谷P1260
spj在最下面


题目描述
造一幢大楼是一项艰巨的工程,它是由n个子任务构成的,给它们分别编号1,2,…,n(5≤n≤1000)。由于对一些任务的起始条件有着严格的限制,所以每个任务的起始时间T1,T2,…,Tn并不是很容易确定的(但这些起始时间都是非负整数,因为它们必须在整个工程开始后启动)。例如:挖掘完成后,紧接着就要打地基;但是混凝土浇筑完成后,却要等待一段时间再去掉模板。
这种要求就可以用M(5≤m≤5000)个不等式表示,不等式形如Ti-Tj≤b代表i和j的起始时间必须满足的条件。每个不等式的右边都是一个常数b,这些常数可能不相同,但是它们都在区间(-100,100)内。
你的任务就是写一个程序,给定像上面那样的不等式,找出一种可能的起始时间序列T1,T2,…,Tn,或者判断问题无解。对于有解的情况,要使最早进行的那个任务和整个工程的起始时间相同,也就是说,T1,T2,…,Tn中至少有一个为0。


分析

  差分约束作为一种建图的方法,将未知量间的约束关系用图来表示.
  在我们求得最短路后,一定满足 dis[v] <= dis[u] + w(u, v);而题目给出的条件也可以转化为T[i] <= T[j] + d,因此可以考虑建个图,根据条件,连边j—>i,权值为d,求最短路即可.
  注意点:
   1.可能存在不联通的情况
   2.有负权,考虑用spfa,顺便判断负环(无解)
  (差分约束可以参考这个blog)


代码

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>

#define IL inline
#define open(s) freopen(s".in", "r", stdin); freopen(s".out", "w", stdout);
#define close fclose(stdin); fclose(stdout);

using namespace std;

IL int read()
{
    int sum = 0;
    bool k = 1;
    char c = getchar();
    for(;'0' > c || c > '9'; c = getchar())
    if(c == '-') k = 0;
    for(;'0' <= c && c <= '9'; c = getchar())
        sum = sum * 10 + c - '0';
    return k ? sum : -sum;
}

struct Edge
{
    int to, nxt, w;
    IL Edge(int to_ = 0, int nxt_ = 0, int w_ = 0)
    {
        to = to_; nxt = nxt_; w = w_;
    }
}edge[5005];
int cnt;
int last[1005];
IL void add(int u, int v, int w)
{
    edge[++cnt] = Edge(v, last[u], w); last[u] = cnt;
}

int n, m;
bool vis[1005];
int dis[1005];
int tot[1005];
int miw;
queue<int>Q;

IL bool spfa(int u)
{
    miw = dis[0]; dis[u] = 0;
    Q.push(u);
    for(; !Q.empty();)
    {
        u = Q.front(); Q.pop(); vis[u] = 0;
        if(dis[u] < miw) miw = dis[u];
        if((++tot[u]) > n) return 1;
        for(int i = last[u], v; i; i = edge[i].nxt)
        {
            v = edge[i].to;
            if(dis[u] + edge[i].w < dis[v])
            {
                dis[v] = dis[u] + edge[i].w;
                if(!vis[v])
                {
                    vis[v] = 1;
                    Q.push(v);
                }
            }
        }
    }
    for(int i = 1; i <= n; ++i)
    if(dis[i] != dis[0])
        dis[i] -= miw;
    return 0;
}

int main()
{
    open("work");

    n = read(); m = read();
    for(int x, y; m; --m)
    {
        x = read(); y = read();
        add(y, x, read());
    }
    memset(dis, 0x3f, sizeof(dis));
    bool f = 0;
    for(int i = 1; i <= n; ++i)
    if(dis[i] == dis[0] && spfa(i))
    {
        f = 1;
        printf("NO SOLUTION\n");
    }
    if(!f)
    {
        for(int i = 1; i <= n; ++i)
            printf("%d\n", dis[i]);
    }

    close
    return 0;
}

SPJ

(没写过几次,有疏忽的地方请指教) 请忽略下面一堆的WAx

#include <bits/stdc++.h>

#define IL inline
using namespace std;

ifstream fin,fout,fstd;
ofstream fscore,freport;

string s1, s2;
int n, m;
int num[1005];

IL bool AC()
{
    return 1;
}

IL bool WA1()
{
    freport<<"expected NO SOLUTION.";
    return 0;
}

IL bool WA2()
{
    freport<<"can't find zero.";
    return 0;
}

IL bool WA3(int i)
{
    freport<<"line "<<i<<" wrong answer.";
    return 0;
}

IL bool WA4()
{
    freport<<"too short.";
    return 0;
}

IL bool WA5()
{
    freport<<"too long.";
    return 0;
}

IL bool WA6()
{
    freport<<"wrong answer.";
    return 0;
}

IL bool WA7()
{
    freport<<"find negative number.";
    return 0;
}

bool judge()
{
    fstd>>s1;
    fout>>s2;
    if(s1 == "NO")
    {
        if(s1 == s2) return AC(); else return WA1();
    }
    if(s2 == "NO") return WA6();
    fin>>n>>m;
    num[1] = atoi(s2.c_str());
    bool f = (num[1] == 0);
    for(int i = 2; i <= n; ++i)
    {
        if(!(fout>>num[i])) return WA4();
        if(!f && !num[i]) f = 1;
    }
    if(!f) return WA2();
    if(fout>>n) return WA5();
    for(int i = 1, x, y, z; i <= m; ++i)
    {
        fin>>x>>y>>z;
        if(num[x] - num[y] > z) return WA3(i);
    }
    return AC();
}

int main(int argc,char *argv[])
{
    std::ios::sync_with_stdio(false);
    fin.open(argv[1]);
    fout.open(argv[2]);
    fstd.open(argv[3]);
    fscore.open(argv[5]);
    freport.open(argv[6]);

    int score = atoi(argv[4]);
    fscore<<score*judge()<<endl;

    fin.close();
    fout.close();
    fstd.close();
    fscore.close();
    freport.close();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_27121257/article/details/81284432