POJ_1860_判断正权环(bellmanford和floyd)

5

POJ 1860
题意:货币种类是点,货币交换是边,能否在交换回来使得金钱变多,意思就是是否存在正环

  • 两层循环 模拟一次流通后 每一个点 的金钱数
  • 将第一次多次循环和第二次比较,若有任意一个点钱数变多则说明存在正环
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    #include <iostream>
    using namespace std;
    const int maxn = 105;
    int n,m,start;
    double money;
    double dist[maxn];
    double profit[maxn][maxn],cost[maxn][maxn];

    bool istrue() {
    double backup[maxn];
    for (int i=1; i<=n; i++) backup[i] = dist[i];
    for (int k=1; k<=n; k++)
    for (int i=1; i<=n; i++)
    for (int j=1; j<=n; j++)
    if ( (dist[i] - cost[i][j]) * profit[i][j] > dist[j] )
    dist[j] = (dist[i] - cost[i][j]) * profit[i][j];
    for (int i=1; i<=n; i++)
    if (dist[i] > backup[i]) return 1;
    return 0;
    }
    int main() {
    // freopen("a.txt","r",stdin);
    cin >> n >> m >> start >> money;
    for (int i=1; i<=m; i++) {
    int u,v;
    double profit1,cost1,profit2,cost2;
    cin >> u >> v >> profit1 >> cost1 >> profit2 >> cost2;
    profit[u][v] = profit1; cost[u][v] = cost1;
    profit[v][u] = profit2; cost[v][u] = cost2;
    }
    dist[start] = money;
    istrue();
    if (istrue()) cout << "YES\n";
    else cout << "NO\n";
    return 0;
    }

bellman_ford 求最大回路是否存在正环

  • 修改松弛条件,dist[i]表示换成货币i的钱,
  • dist[]初始化为负的最小值,源点为起始金钱,向外松弛,记录每个点的松弛次数,
  • 只要存在正环,那么某个点肯定会一直松弛下去,通过这个判断
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    #include <iostream>
    #include <vector>
    #include <queue>
    #include <string.h>

    using namespace std;
    const int maxn = 105;
    const int MIN = -0x3f3f3f3f;

    struct node {
    int from,to;
    double profit,cost;
    node (){};
    node (int a,int b,double c,double d) {
    from = a; to = b; profit = c; cost = d;
    }
    };
    vector<node> edges;
    vector<int> e[maxn];
    int n,m,start;
    double money;
    double dist[maxn];
    bool vis[maxn];
    int cnt[maxn];

    void addedge(int u,int v,double profit1,double cost1,double profit2,double cost2) {
    edges.push_back( node(u,v,profit1,cost1) );
    edges.push_back( node(v,u,profit2,cost2) );
    int id = edges.size();
    e[u].push_back(id-2);
    e[v].push_back(id-1);
    }
    bool bellmanford() {
    queue<int> que;
    for (int i=1; i<=n; i++) dist[i] = MIN;
    memset(vis,0,sizeof vis);
    vis[start] = 1; dist[start] = money;
    que.push(start);
    while (!que.empty()) {
    int cur = que.front(); que.pop();
    vis[cur] = 0;
    for (int i=0; i<e[cur].size(); i++) {
    int id = e[cur][i];
    node& tmp = edges[id];
    if (dist[tmp.to] < (dist[cur] - tmp.cost)*tmp.profit) {
    dist[tmp.to] = (dist[cur] - tmp.cost) * tmp.profit;
    if (!vis[tmp.to]) {
    que.push(tmp.to);
    vis[tmp.to] = 1;
    if (++cnt[tmp.to] > n) return 1;
    }
    }
    }
    }
    return 0;
    }
    int main() {
    // freopen("a.txt","r",stdin);
    cin >> n >> m >> start >> money;
    for (int i=1; i<=m; i++) {
    int u,v;
    double profit1,cost1,profit2,cost2;
    cin >> u >> v >> profit1 >> cost1 >> profit2 >> cost2;
    addedge(u,v,profit1,cost1,profit2,cost2);
    }
    if (bellmanford()) cout << "YES\n";
    else cout << "NO\n";
    return 0;
    }

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!