[POJ 2983]Is the Information Reliable?[差分约束]

题目链接: [POJ 2983]Is the Information Reliable?[差分约束]

题意分析:

给出N个防御站和M个提示,提示P代表A站在B站的北方X米处,提示V代表,A站在B站北方至少1米处,现在问:给出的这M个提示是否可信?

解题思路:

对于P操作,我们得知dis[B] - dis[A] == x 转换为:dis[B] - dis[A] <= x && dis[B] - dis[A] >= x,再根据V,得知:dis[B] - dis[A] >= 1。根据上次说的,写出方程后,写出转移if (dis[B] < dis[A] + 1) dis[B] = dis[A] + 1。可知,是求最长路。如果有矛盾出现的话,就会形成环,这个不妨画图就清楚了:


当出现矛盾时,就会出现不等关系后,必然会造成增得比减的多的情况。上图:1->2->3->1

个人感受:

差分约束,我天= =。只能说这种东西太牛了。。。。我想过并查集或者直接找矛盾,只能说这种方法太6了。。。。然后我太弱了TAT

具体代码如下:

#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iomanip>
#include<iostream>
#include<map>
#include<queue>
#include<set>
#include<sstream>
#include<stack>
#include<string>
#define pr(x) cout << #x << " = " << (x) << '\n';
using namespace std;

const int INF = 0x7f7f7f7f;
const int MAXN = 1e3 + 111;
const int MAXM = 3e5 + 111;

struct Edge{
    int next, to, w;
}edge[MAXM];

int head[2 * MAXN], tol;

void addedge(int u, int v, int w) {
    edge[tol].next = head[u];
    edge[tol].to = v;
    edge[tol].w = w;
    head[u] = tol++;
}

int dis[MAXN], num[MAXN];
bool in[MAXN];
bool spfa(int n, int s) {
    for (int i = 1; i <= n; ++i) {
        dis[i] = -INF;
        in[i] = num[i] = 0;
        addedge(s, i, 0);
    }
    queue<int> q;
    q.push(s);
    dis[s] = 0;
    in[s] = 1;
    ++num[s];
    while (q.size()) {
        int u = q.front(); q.pop();
        in[u] = 0;
        for (int i = head[u]; ~i; i = edge[i].next) {
            int v = edge[i].to;
            if (dis[v] < dis[u] + edge[i].w) {
                dis[v] = dis[u] + edge[i].w;
                if (!in[v]) {
                    q.push(v);
                    in[v] = 1;
                    if (++num[v] > n) return 1;
                }
            }
        }
    }
    return 0;
}

int main()
{
    int n, m, a, b, c;
    char op[2];
    while (~scanf("%d%d", &n, &m)) {
        memset(head, -1, sizeof head);
        tol = 0;
        for (int i = 0; i < m; ++i) {
            scanf("%s%d%d", op, &a, &b);
            if (op[0] == 'P') {
                scanf("%d", &c);
                addedge(a, b, c);
                addedge(b, a, -c);
            }
            else {
                addedge(a, b, 1);
            }
        }

        if (spfa(n, 0)) printf("Unreliable\n");
        else printf("Reliable\n");
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值