Description
P3275
给定 (n) 个整数 (t_i) 和 (k) 个不等式,这 (k) 个不等式有如下几种
- (t_i=t_j)
- (t_i<t_j)
- (t_i ge t_j)
- (t_i>t_j)
- (t_ile t_j)
最后输出[sumlimits_{i=1}^nt_i ]如果无解输出 (-1)。
Solution
差分约束,但这种形式还是很难搞差分,所以我们要转化一下,成这样:
- (t_i ge t_j) or (t_j ge t_i)
- (t_j ge t_i+1)
- (t_i ge t_j)
- (t_i ge t_j+1)
- (t_j ge t_i)
我们一旦在差分约束题中发现 (a ge b) 的形式,那么我们就要开始算 最长路。
并且还有一个约束条件:(t_i >1)。
注意最长路与最短路的几个区别:
- (dist_i=min{dist_j+<i,j>}) 的转化式要变为 (dist_i=max{dist_j+<i,j>})
- (dist_i) 的初始值要从 ( m inf) 变为 ( m - inf)
对于这道题,因为 (t_i > 1),所以在差分约束建超级源点的时候要注意边权 (w) 要设为 (1)。
然后根据差分约束模板的思路转化就可以。
Code 1
#include <bits/stdc++.h>
using namespace std;
struct node {
int val, next, len;
} e[1000086];
int n, k;
int cnt;
int head[1000086];
int dist[1000086];
int sum[1000086];
int vis[1000086];
int S[1000086];
const int inf = 0x3f3f3f3f;
void AddEdge (int u, int v, int w) {
e[++cnt].val = v;
e[cnt].next = head[u];
e[cnt].len = w;
head[u] = cnt;
}
bool SPFA () {
queue <int> q;
int s = 0;
for (int i = 1; i <= n; i++)
dist[i] = -inf;
dist[s] = 0;
sum[s] = 1;
vis[s]++;
q.push(s);
while (!q.empty()) {
int cur = q.front();
q.pop();
sum[cur] = 0;
for (int p = head[cur]; p > 0; p = e[p].next)
if (dist[e[p].val] < dist[cur] + e[p].len) {
dist[e[p].val] = dist[cur] + e[p].len;
vis[e[p].val]++;
if (vis[e[p].val] >= n + 1)
return true;
if (!sum[e[p].val]) {
q.push(e[p].val);
sum[e[p].val] = 1;
}
}
}
return false;
}
int main () {
scanf("%d%d", &n, &k);
for (int i = 1, opt, u, v; i <= k; i++) {
scanf("%d%d%d", &opt, &u, &v);
if (opt == 1) AddEdge(u, v, 0), AddEdge(v, u, 0);
if (opt == 2) AddEdge(u, v, 1);
if (opt == 3) AddEdge(v, u, 0);
if (opt == 4) AddEdge(v, u, 1);
if (opt == 5) AddEdge(u, v, 0);
}
for (int i = 1; i <= n; i++)
AddEdge(0, i, 1);
if (SPFA()) {
printf("-1");
return 0;
}
int ans = 0;
for (int i = 1; i <= n; i++)
ans += dist[i];
printf("%d", ans);
return 0;
}
预测得分:(80) 分
wdnmd …… 这 TLE 是咋回事?
所以我们要特判
Code 2
#include <bits/stdc++.h>
using namespace std;
struct node {
int val, next, len;
} e[1000086];
int n, k;
int cnt;
int head[1000086];
int dist[1000086];
int sum[1000086];
int vis[1000086];
int S[1000086];
const int inf = 0x3f3f3f3f;
void AddEdge (int u, int v, int w) {
e[++cnt].val = v;
e[cnt].next = head[u];
e[cnt].len = w;
head[u] = cnt;
}
bool SPFA () {
queue <int> q;
int s = 0;
for (int i = 1; i <= n; i++)
dist[i] = -inf;
dist[s] = 0;
sum[s] = 1;
vis[s]++;
q.push(s);
while (!q.empty()) {
int cur = q.front();
q.pop();
sum[cur] = 0;
for (int p = head[cur]; p > 0; p = e[p].next)
if (dist[e[p].val] < dist[cur] + e[p].len) {
dist[e[p].val] = dist[cur] + e[p].len;
vis[e[p].val]++;
if (vis[e[p].val] >= n + 1)
return true;
if (!sum[e[p].val]) {
q.push(e[p].val);
sum[e[p].val] = 1;
}
}
}
return false;
}
int main () {
scanf("%d%d", &n, &k);
for (int i = 1, opt, u, v; i <= k; i++) {
scanf("%d%d%d", &opt, &u, &v);
if (opt != 1 && opt != 3 && opt != 5 && u == v) {
printf("-1");
return 0;
}
if (opt == 1) AddEdge(u, v, 0), AddEdge(v, u, 0);
if (opt == 2) AddEdge(u, v, 1);
if (opt == 3) AddEdge(v, u, 0);
if (opt == 4) AddEdge(v, u, 1);
if (opt == 5) AddEdge(u, v, 0);
}
for (int i = 1; i <= n; i++)
AddEdge(0, i, 1);
if (SPFA()) {
printf("-1");
return 0;
}
int ans = 0;
for (int i = 1; i <= n; i++)
ans += dist[i];
printf("%d", ans);
return 0;
}
预测得分:(90) 分
这卡常 …… 还能卡一个 TLE
那么我们还可以怎么优化呢?
用 deque 一优化就可以了!
Code 3
#include <bits/stdc++.h>
using namespace std;
struct node {
int val, next, len;
} e[1000086];
int n, k;
int cnt;
int head[1000086];
int dist[1000086];
int sum[1000086];
int vis[1000086];
int S[1000086];
const int inf = 0x3f3f3f3f;
void AddEdge (int u, int v, int w) {
e[++cnt].val = v;
e[cnt].next = head[u];
e[cnt].len = w;
head[u] = cnt;
}
bool SPFA () {
deque <int> q;
int s = 0;
for (int i = 1; i <= n; i++)
dist[i] = -inf;
dist[s] = 0;
sum[s] = 1;
vis[s]++;
q.push_front(s);
while (!q.empty()) {
int cur = q.front();
q.pop_front();
sum[cur] = 0;
for (int p = head[cur]; p > 0; p = e[p].next)
if (dist[e[p].val] < dist[cur] + e[p].len) {
dist[e[p].val] = dist[cur] + e[p].len;
vis[e[p].val]++;
if (vis[e[p].val] >= n + 1)
return true;
if (!sum[e[p].val]) {
q.push_front(e[p].val);
sum[e[p].val] = 1;
}
}
}
return false;
}
int main () {
scanf("%d%d", &n, &k);
for (int i = 1, opt, u, v; i <= k; i++) {
scanf("%d%d%d", &opt, &u, &v);
if (opt != 1 && opt != 3 && opt != 5 && u == v) {
printf("-1");
return 0;
}
if (opt == 1) AddEdge(u, v, 0), AddEdge(v, u, 0);
if (opt == 2) AddEdge(u, v, 1);
if (opt == 3) AddEdge(v, u, 0);
if (opt == 4) AddEdge(v, u, 1);
if (opt == 5) AddEdge(u, v, 0);
}
for (int i = 1; i <= n; i++)
AddEdge(0, i, 1);
if (SPFA()) {
printf("-1");
return 0;
}
long long ans = 0;
for (int i = 1; i <= n; i++)
ans += (1ll * dist[i]);
printf("%lld", ans);
return 0;
}
预测得分:(100) 分
AC Record
By Shuchong
2020.7.15