EOJ 1270 spfa/floyd

来源:互联网 发布:python搭建个人博客 编辑:程序博客网 时间:2024/05/21 17:38

题意不再赘述。首先建图。我们将一个点周围的点都给兑换成这个点,然后选择最大的值作为这个点的价值,然后这样不断的计算下去,直到计算到初始点,如果我们重新计算的价值大于初始点的值,就表明有兑换漏洞。这个过程看起来是不是很像求最短路呢?只不过我们把更新公式d[v] = min(d[v], d[u] + w[u][v])换成了d[v] = max(d[v], d[u]*w[u][v]),并且d[v]的含义也发生了变化,原来的d表示从初始点到v的最短距离,现在的d[v]表示从价值为1的初始点开始兑换,兑换到v这个点我们能够获得的最大价值。思路相似,我们套用最短路模板,但是我们求得并不是最短路。因为汇率可能小于1,即权值为负。不能用dijkstra。我们使用spfa或者floyd。

具体思路就是从源点src开始套用最短路模板不断的更新,更新结束后我们看一下d[src][src](从价值为1的初始点开始兑换,经历一系列过程再次兑换成初始点所能获得的最大价值)是不是大于初始值,如果大于,就输出yes。

因为对每个点都要spfa,所以我们也可以选择floyd。状态转移公式也变成了d[i][j] = max(d[i][j], d[i][k] * d[k][j])(注意d[i][j]是我们假设初始值是1,得到的答案。如果初始值为a,就要相应的乘以a倍。这也是状态转移公式用乘号的原因)。

spfa代码:

#include <algorithm>#include <iostream>#include <cstring>#include <cstdlib>#include <cstdio>#include <cmath>#include <queue>#include <map> using namespace std; const int maxn = 1005;double G[maxn][maxn];int n, m; bool spfa(int src){    int Inqueue[maxn];    double d[maxn];    memset(Inqueue, 0, sizeof(Inqueue));    memset(d, 0, sizeof(d));    queue<int> Q;    Q.push(src);    Inqueue[src] = 1;    d[src] = 1.0;    while (!Q.empty()){        int u = Q.front();        Q.pop();        Inqueue[u] = 0;        for (int v = 1; v <= n; v++){            if (G[u][v]){                double cost = G[u][v];                if (d[v] < d[u] * cost){                    d[v] = d[u] * cost;                    if (!Inqueue[v]){                        Q.push(v);                        Inqueue[v] = 1;                    }                    if (d[src] > 1.0) return true;                }            }        }    }    return false;} int main(){    //freopen("1.txt", "r", stdin);    int Case = 1;    while (~scanf("%d", &n) && n){        map<string, int> msi;        char name[50];        for (int i = 1; i <= n; i++){            scanf("%s", name);            msi[name] = i;        }        scanf("%d", &m);        char u[50], v[50];        double cost;        memset(G, 0, sizeof(G));        for (int i = 0; i < m; i++){            scanf("%s%lf%s", u, &cost, v);            int uu = msi[u], vv = msi[v];            G[uu][vv] = cost;        }         printf("Case %d: ", Case++);         int ok = 0;        for (int i = 1; i <= n; i++){            if (spfa(i)){                ok = 1;                break;            }        }        if (ok) printf("Yes\n");        else printf("No\n");    }    return 0;}

floyd代码:

#include <algorithm>#include <iostream>#include <cstring>#include <cstdlib>#include <cstdio>#include <cmath>#include <queue>#include <map> using namespace std; const int maxn = 1005;int n, m;double d[maxn][maxn]; void Init(){    for (int i = 1; i <= n; i++)    for (int j = 1; j <= n; j++){        if (i == j) d[i][j] = 1;        else d[i][j] = 0;    }} void floyd(){    for (int k = 1; k <= n; k++)    for (int i = 1; i <= n; i++)    for (int j = 1; j <= n; j++){        if (d[i][j] < d[i][k] * d[k][j])           d[i][j] = d[i][k] * d[k][j];    }} int main(){    //freopen("1.txt", "r", stdin);    int Case = 1;    while (~scanf("%d", &n) && n){        map<string, int> msi;        char name[50];        for (int i = 1; i <= n; i++){            scanf("%s", name);            msi[name] = i;        }        scanf("%d", &m);        Init();        char u[50], v[50];        double cost;        for (int i = 1; i <= m; i++){            scanf("%s%lf%s", u, &cost, v);            int uu = msi[u], vv = msi[v];            d[uu][vv] = cost;        }         floyd();         printf("Case %d: ", Case++);        int i;        for (i = 1; i <= n; i++){            if (d[i][i] > 1){                printf("Yes\n");                break;            }        }        if (i == n + 1) printf("No\n");    }    return 0;}


0 0
原创粉丝点击