NYOJ 973 天下第一(最长路判环)

题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=973

题目大意:给你n种武功,每两种武功都可以相互转化,但是有转化率f, 每次必须从一开始转化, 中间有武功转化不了, 后面的就不能在转化了, 问你能否可以无限增加转化。

在做这道题以前做了和这道题一样的一道题, 所以我认为很快就能AC了, 但是这道题我还是弄了一天还是没能AC。来讲一下让我很是郁闷的问题吧。 这道题可以用最短路判环(spfa只需稍微变一下)来做,也可以用直接深搜来做。我的最初想法就是深搜来做。我上一道题就是用深搜做的,我就开始写了, 然后就是各种WA, 后来搞到后台数据找到一组错误的输出, 然后就是各种改, 最终还是WA, 没办法了, 我就写了一个spfa, 然后就AC了, 看来正解还是spfa,
现在我还是不明白我以前的为什么错。所以发个博客记录一下, 以免在出现这种情况。同时想让路过的大牛给解释一下。

下面是代码

AC的

#include<stdio.h>
#include<string.h>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
const int maxn = 500 + 10;
struct Edge
{
    int v;
    double f;
    Edge(int i, double j) : v(i), f(j) {}
};
vector<Edge> G[maxn];
double d[maxn];
int cnt[maxn];
bool inq[maxn];
bool spfa(int s, int n)
{
    queue<int> Q;
    memset(inq, false, sizeof(inq));
    memset(d, 0, sizeof(d));
    memset(cnt, 0, sizeof(cnt));
    d[s] = 1.0;
    inq[s] = true;
    Q.push(s);
    while(!Q.empty())
    {
        int u = Q.front();
        Q.pop();
        inq[u] = false;
        for(int i = 0; i < G[u].size(); i++)
        {
            int v = G[u][i].v;
            double ff = G[u][i].f;
            if(d[v]<d[u]*ff)
            {
                d[v] = d[u]*ff;
                if(!inq[v])
                {
                    Q.push(v);
                    inq[v] = true;
                    if(++cnt[v] >= n)
                        return true;
                }
            }
        }
    }
    return false;
}
int main()
{
    int T, n, m, a, b;
    double ff;
//    freopen("Input.txt", "r", stdin);
//    freopen("O.txt", "w", stdout);
    scanf("%d", &T);
    while(T--)
    {
        scanf("%d%d", &n, &m);
        for(int i = 0; i <= n; i++)
            G[i].clear();
        while(m--)
        {
            scanf("%d%lf%d", &a, &ff, &b);
            G[a].push_back(Edge(b, ff));
        }
        if(spfa(1, n))
            puts("Yes");
        else
            puts("No");
    }
    return 0;
}

WA的

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn = 500 + 10;
int vis[maxn];
int pre[maxn];
struct Info
{
    int to;
    double f;
    Info(int i, double j) :to(i), f(j) {}
};
vector<Info> G[maxn];
bool dfs(int rt, int u, double ans)
{
    vis[u] = -1;
    for(int i = 0; i < G[u].size(); i++)
    {
        Info x = G[u][i];
        int v = x.to;
        pre[v] = pre[u];
        double Ans = ans * x.f;
        if(Ans == 0)
            continue;
        if(v==rt)
        {
            if(Ans>1.0)
                return true;
        }
        if(!vis[v] && dfs(rt, v, Ans))
            return true;
    }
    vis[u] = 1;
    return false;
}
int main()
{
    int T, n, m;
//    freopen("Input.txt", "r", stdin);
//    freopen("O.txt", "w", stdout);
    scanf("%d", &T);
    while(T--)
    {
        memset(pre, -1, sizeof(pre));
        scanf("%d%d", &n, &m);
        for(int i = 0; i <= n; i++)
            G[i].clear();
        while(m--)
        {
            int a, b;
            double ff;
            scanf("%d%lf%d", &a, &ff, &b);
            G[a].push_back(Info(b, ff));
        }
        bool flag = false;
        pre[1] = 1;
        for(int i = 1; i <= n; i++)
        {
            memset(vis, 0, sizeof(vis));
            if(pre[i]==1 && dfs(i, i, 1.0))
            {
                flag = true;
                break;
            }
        }
        if(flag)
            printf("Yes\n");
        else
            printf("No\n");
    }
    return 0;
}
这是深搜的wa的代码,唯一一组出现错误测试数据
33肿武功, 93种转化   应该输出Yes    如果直接暴搜就会超时
33 93
30 0.3 32
23 0.9 6
18 0.9 21
13 0.9 14
21 1.2 11
28 0 24
32 0.5 29
23 1.1 12
26 0.5 8
7 0.1 12
6 1.4 33
29 0.9 30
12 1.3 6
10 0.4 32
33 0.2 6
9 0.5 12
24 1.7 22
4 1 11
3 0.5 1
1 0.8 2
20 0 7
5 1.7 15
13 1.1 16
7 0.7 21
30 0.6 31
18 0.9 10
28 1.7 14
31 0.8 33
27 1.6 15
29 0.4 19
26 0.9 2
23 0.8 5
20 0.4 6
29 1 7
11 1.6 31
30 0.6 17
18 1.5 23
21 1.2 32
21 0.4 16
6 0.3 20
13 0 33
7 0.3 32
14 0.2 4
7 0.3 28
14 0.7 9
17 0.9 28
1 0.1 19
3 0.9 7
11 0.8 29
33 1.9 10
9 0.7 13
7 0.3 17
5 0.1 21
18 0 16
9 1.7 5
11 0.7 10
20 1.2 14
13 0.5 22
29 0.3 23
12 0 21
1 0.1 16
29 1.3 25
1 0.7 29
6 0.9 25
4 0.3 8
27 1.5 14
11 0.5 17
4 1.8 33
32 1.4 26
11 0.2 32
30 0.2 7
29 1.6 5
18 0.2 6
8 0.4 28
23 1.8 33
17 1.3 23
16 0.5 13
22 0.3 26
25 0.7 22
2 1.6 32
16 1.6 26
33 1.8 8
19 0.2 29
28 0.5 13
23 1.8 24
8 0.7 5
19 1.1 23
27 0.9 5
16 0.7 22
19 1.3 9
28 1.9 26
31 0.8 6
25 1 16
时间: 2024-10-03 02:53:49

NYOJ 973 天下第一(最长路判环)的相关文章

POJ2240:Arbitrage(最长路+正环)

Arbitrage Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 29374   Accepted: 12279 题目链接:http://poj.org/problem?id=2240 Description: Arbitrage is the use of discrepancies in currency exchange rates to transform one unit of a currency into

NYOJ 973 天下第一

题目连接:http://acm.nyist.net/JudgeOnline/problem.php?pid=973 算法分析: spfa+负环判定 在传功的过程中如果因为f<1导致逐渐变小,那么即可以负环判定 #include <iostream> #include<cstdio> #include <cstdlib> #include <queue> #include <vector> using namespace std; const

hdu 1317 SPFA+连通判断+最长路

Description It has recently been discovered how to run open-source software on the Y-Crate gaming device. A number of enterprising designers have developed Advent-style games for deployment on the Y-Crate. Your job is to test a number of these design

HDU 3249 Test for job (有向无环图上的最长路,DP)

 解题思路: 求有向无环图上的最长路,简单的动态规划 #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <algorithm> #include <vector> #include <cmath> #define LL long long using namespace std; const int

hdu 1317 XYZZY(spfa判环)

http://acm.hdu.edu.cn/showproblem.php?pid=1317 大致题意:有n个房间,每个房间都有对应的能量值(可正可负),现在从1出发要到达n,初始能量为100,问是否能够达到n点,到达n的条件是中间及最后的能量值都要大于0. 思路:若不考虑环,那么求最长路判断是否大于0即可.若存在负环,对求最长路也没影响:但当存在正环时,最长路就不存在了.可用spfa判断,当某点入队超过n次,那么它必定在环中,直接将其dis置为INF,并不再将其近队列.最后若能到达n则可行,否

NYIST 973 天下第一

天下第一时间限制:1000 ms | 内存限制:65535 KB难度:3 描述AC_Grazy一直对江湖羡慕不已,向往着大碗吃肉大碗喝酒的豪情,但是“人在江湖漂,怎能 不挨刀",”人在江湖身不由己",如果自己的武功太差,在江湖会死的很惨,但是AC_Grazy没有 武功秘籍练不了绝世武功.有道是“山重水复疑无路,柳暗花明又一村”,在AC_Grazy家里面 竟然藏着一本书,书名竟然叫做[超级外挂],竟然能在各种武功之间进行转化,据说是他爷 爷的爷爷的...爷爷传下来的... 闲着无事便拿来

SDUTOJ 2498 AOE网上的关键路径(最长路)

AOE网上的关键路径 Time Limit: 1000MS Memory limit: 65536K 题目描述 一个无环的有向图称为无环图(Directed Acyclic Graph),简称DAG图. AOE(Activity On Edge)网:顾名思义,用边表示活动的网,当然它也是DAG.与AOV不同,活动都表示在了边上,如下图所示: 如上所示,共有11项活动(11条边),9个事件(9个顶点).整个工程只有一个开始点和一个完成点.即只有一个入度为零的点(源点)和只有一个出度为零的点(汇点)

P1807 最长路_NOI导刊2010提高(07)

P1807 最长路_NOI导刊2010提高(07) 题目描述 设G为有n个顶点的有向无环图,G中各顶点的编号为1到n,且当为G中的一条边时有i < j.设w(i,j)为边的长度,请设计算法,计算图G中<1,n>间的最长路径. 输入输出格式 输入格式: 输入文件longest.in的第一行有两个整数n和m,表示有n个顶点和m条边,接下来m行中每行输入3个整数a,b,v(表示从a点到b点有条边,边的长度为v). 输出格式: 输出文件longest.out,一个整数,即1到n之间的最长路径.如

POJ3592 Instantaneous Transference 强连通+最长路

题目链接: poj3592 题意: 给出一幅n X m的二维地图,每个格子可能是矿区,障碍,或者传送点 用不同的字符表示: 有一辆矿车从地图的左上角(0,0)出发,只能往右走或往下走,或者通过传送点  选择是否 传送到特定地点 采过的矿的格子 矿会消失;问这辆矿车最多能采多少矿 解题思路: 首先重新建图,将图中二维的顶点压缩成一维的顶点             (方便Tarjan算法) 每个顶点往右,下的顶点建边,传送点的格子往特定顶点建边(建边的两端不能有障碍) 得到一幅可能存在环的有向图;