差分约束束束束束束束

本文介绍了洛谷算法竞赛中涉及的两个问题,分别是使用差分约束进行路径求解(如P5960)和树结构构建(如P1250),以及一个矩阵问题(HDUTHEMATRIXPROBLEM),通过SPFA算法实现优化求解。
摘要由CSDN通过智能技术生成

洛谷 P5960 【模板】差分约束算法

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 2e5 + 10;
const int mod = 998244353;
typedef pair<int, int> PII;
int n, m, q, k;
int a[N], b[N];

vector<PII> g[N];
int vis[N], dist[N], cnt[N];
int spfa(){
    memset(dist, 0x3f, sizeof(dist));
    queue<int64_t> q;
    q.push(0);
    vis[0] = 0;
    dist[0] = 0;
    while(q.size()){
        int u = q.front();
        q.pop();
        if(cnt[u] > n){
            return 0;
        }
        vis[u] = 0;
        for(auto i : g[u]){
            if(dist[i.first] > dist[u] + i.second){
                dist[i.first] = dist[u] + i.second;
                if(vis[i.first]){
                    continue;
                }
                q.push(i.first);
                vis[i.first] = 1;
                cnt[i.first] ++;    
            }
            
        }
    }
    return 1;
}
void solve(){
    cin >> n >> m;
    // xi - xj <= c
    for(int i = 1; i <= m; i++){
        int u, v, w;
        cin >> u >> v >> w;
        g[v].push_back({u, w});
    }
    for(int i = 1; i <= n; i++){
        g[0].push_back({i, 0});
    }
    if(spfa()){
        for(int i = 1; i <= n; i++){
            cout << dist[i] << " \n"[i == n];
        }
    }else{
        cout << "NO\n";
    }
}


signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int t = 1;
    // cin >> t;
    while(t--){
        solve();
    }
    return 0;
}

洛谷 P1250 种树

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 2e5 + 10;
const int mod = 998244353;
typedef pair<int, int> PII;
int n, m, q, k;
int a[N], b[N];

vector<PII> g[N];
int vis[N], dist[N], cnt[N];
int spfa(){
    memset(dist, 0x3f, sizeof(dist));
    queue<int64_t> q;
    q.push(n + 1);
    vis[n + 1] = 1;
    dist[n + 1] = 0;
    while(q.size()){
        int u = q.front();
        q.pop();
        if(cnt[u] > n){
            return 0;
        }
        vis[u] = 0;
        for(auto i : g[u]){
            if(dist[i.first] > dist[u] + i.second){
                dist[i.first] = dist[u] + i.second;
                if(vis[i.first]){
                    continue;
                }
                q.push(i.first);
                vis[i.first] = 1;
                cnt[i.first] ++;    
            }
            
        }
    }
    return 1;
}
void solve(){
    cin >> n >> m;
    // ei - bi >= t 
    // bi - ei <= -t
    // bi <= -t + ei
    for(int i = 1; i <= m; i++){
        int b, e, t;
        cin >> b >> e >> t;
        g[e].push_back({b - 1, -t});
    }
    for(int i = 0; i <= n; i++){
        g[i].push_back({i + 1, 1});
        g[i + 1].push_back({i, 0});
        // 0 <= sumi+1 - sumi <= 1
        // sumi+1 <= sumi + 1
        // sumi <= sumi+1 + 0
    }
    if(spfa()){
        cout << -dist[0] << "\n";
    }else{
        cout << "NO\n";
    }
}


signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int t = 1;
    // cin >> t;
    while(t--){
        solve();
    }
    return 0;
}

HDU THE MATRIX PROBLEM

#include<bits/stdc++.h>
using namespace std;
// #define int long long
const int N = 1000;
const int mod = 998244353;
typedef pair<int, double> PII;
int n, m, q, k;
int a[N], b[N];

vector<PII> g[N];
bool vis[N];
double dist[N];
int cnt[N];
int spfa(){
    queue<int> q;
    for(int i = 1; i <= n + m; i++){
        dist[i] = 1e18;
        vis[i] = 0;
        cnt[i] = 0;
    }
    q.push(0);
    vis[0] = 1;
    dist[0] = 0;
    cnt[0] = 0;
    while(q.size()){
        int u = q.front();
        q.pop();
        vis[u] = 0;
        for(auto i : g[u]){
            if(dist[i.first] > dist[u] + i.second){
                dist[i.first] = dist[u] + i.second;
                cnt[i.first] = cnt[u] + 1;
                if(cnt[i.first] == n + m){
                    return 0;
                }
                if(vis[i.first]){
                    continue;
                }
                q.push(i.first);
                vis[i.first] = 1;
                cnt[i.first] ++;   
            }
            
        }
    }
    return 1;
}
void solve(){
    int l, u;
    cin >> l >> u;
    for(int i = 1; i <= n + m; i++){
        g[i].clear();
        g[0].push_back({i, 0});
    }
    // l <= cij * ai / bj <= u
    // log(l / cij) <= log(ai) - log(bi) <= log(u / cij)
    // log(bi) <= log(cij / l) + log(ai)
    // log(ai) <= log(u / cij) + log(bi) 
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= m; j++){
            int x;
            cin >> x;
            g[i].push_back({j + n, log((double)x / l)});
            g[j + n].push_back({i, log((double)u / x)});
        }
    }
    if(spfa()){
        cout << "YES\n";
    }else{
        cout << "NO\n";
    }
}


signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int t = 1;
    // cin >> t;
    while(cin >> n >> m){
        solve();
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值