传送门:洛谷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;
}