其他分享
首页 > 其他分享> > 「题解」Solution P3275

「题解」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

建议先看一看差分约束前置知识。

差分约束,但这种形式还是很难搞差分,所以我们要转化一下,成这样:

我们一旦在差分约束题中发现 \(a \ge b\) 的形式,那么我们就要开始算 最长路

并且还有一个约束条件:\(t_i >1\)。

注意最长路与最短路的几个区别:

对于这道题,因为 \(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