poj2983 差分约束 超级源点

题意: 判定
思路:差分约束。。 建立超级源点。。
此处附上我对超级源点的理解。。一句话: 只能用来判定,不可用来求值。至于为什么,仔细想想。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
using namespace std;
#define rep(i,a,n) for (int i=a;i<=n;i++)
#define per(i,n,a) for (int i=n;i>=a;i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define fi first
#define se second
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const ll mod=1000000007;
ll powmod(ll a,ll b) {ll res=1;a%=mod;for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
#define Fast_IO ios_base::sync_with_stdio(0);cin.tie(0)
const int maxn = 1010;
const int maxm = 500010;
struct node
{
    int v,w,next;
}edge[maxm];
int head[maxn];
int tot;
const int INF = 0x3f3f3f3f;
void init()
{
    tot = 0;
    memset(head, -1, sizeof(head));
}
void add_edge(int u, int v, int w)
{
    edge[tot].v = v;
    edge[tot].w = w;
    edge[tot].next = head[u];
    head[u] = tot++;
}
int n,m;
bool spfa(int st)
{
    bool vis[maxn] = {false};
    int dis[maxn];
    memset(dis, -INF, sizeof(dis));
    queue<int> q;
    q.push(st);
    vis[st] = true;
    dis[st] = 0;
    int cnt[maxn] = {0};
    cnt[st] ++;
    while(!q.empty())
    {
        int u = q.front();
        q.pop();
        vis[u] = false;
        for(int i=head[u]; ~i; i=edge[i].next)
        {
            int v = edge[i].v;int w = edge[i].w;
            if(dis[v] < dis[u] + w)
            {
                dis[v] = dis[u] + w;
                if(!vis[v])
                {
                    vis[v] = true;
                    q.push(v);
                    cnt[v] ++;
                    if(cnt[v] > n)
                        return false;
                }
            }
        }
    }
    return true;
}

int main()
{
    while(cin>>n>>m)
    {
            init();
            char op[3];
            int x,y,z;
            bool flag = false;
            while(m--)
            {
                scanf("%s", op);
                if(op[0] == 'P')
                {
                    scanf("%d %d %d", &x, &y, &z);
                    add_edge(x, y, z);
                    add_edge(y, x, -z);
                    if(x == y && z != 0) flag = true;
                }
                else
                {
                    scanf("%d %d", &x, &y);
                    add_edge(x, y, 1); 
                    if(x == y) flag = true;
                }
            }
        rep(i, 1, n)
            add_edge(0, i, 0);
        bool res = spfa(0);
        if(res&&!flag) puts("Reliable");
        else puts("Unreliable");
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值