「题解」Solution P3275
作者:互联网
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_i\le t_j\)
最后输出\[\sum\limits_{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\) 的初始值要从 \(\rm inf\) 变为 \(\rm -\ 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
标签:1000086,P3275,dist,val,int,题解,Solution,len,cnt 来源: https://www.cnblogs.com/Shu-chong/p/13303860.html