zzuoj 10408

此题是河南省第八届acm C题  点击打开链接

比赛时写这道题由于学长给了一种奇葩的建图方式 导致浪费了两个小时去写搜索 当然最终也没有过这道题 后来和老板他们讨论 说起配合的问题 说不应该先听队友的思路 否则容易被先入为主 没有别的想法 在轻院已经吃亏 由于长期缺乏组队经验 我并没有意识到改正 正确的应该自己也看下题 想想自己的思路 然后和队友去讨论


当时的建图方法是 是 a b c d    然后 a b 一条变 权值为1    然后 b c  1   c  d  1    然而对于这样的奇葩建图方式我并没有产生任何的怀疑 后来下场自己想想实际都觉的可笑  单程公交线 怎么不应该这样建图  正确的建图方法 应该是 a 到 b c d  各有一条权值为1的边 然后是 b  到 c d    c 到d  只要建好图 直接求最短路即可


听人说这道题是原题 其实 图论里面的基本知识只是在大一匆匆学习了一下 知道有那么回事 所以很难以灵活运用  不会变形使用  还是需要把基础算法学牢 不要贪多


重点就是建图 建好图直接dijkstra 求最短路  floyd会超时


另外郑州oj上的数据仍旧有误 好像已经修正了 但是样例的数据还是错的

#include <iostream>
#include <algorithm>
#include <queue>
#include <cstring>
#include <cstdio>
#include <vector>
#include <string>
#include <iterator>
#include <cmath>
#include <deque>
#include <stack>
#include <cctype>
#include <iomanip>
using namespace std;
 
typedef long long ll;
typedef long double ld;
 
const int N = 510;
const int INF = 0xfffffff;
const double EPS = 1e-8;
const ll MOD = 1e9 + 7;
const ld PI = acos (-1.0);
 
#define INFL 0x7fffffffffffffffLL
#define met(a, b) memset(a, b, sizeof(a))
#define put(a) cout << setiosflags(ios::fixed) << setprecision(a)
 
int g[N][N], vis[N], dis[N];
void dijkstra (int n);
 
int main ()
{
    int n, m, t;
    scanf ("%d", &t);
    while (t--)
    {
        scanf ("%d%d", &m, &n);
        for (int i=0; i<=n; i++)
            for (int j=0; j<=n; j++)
                g[i][j] = INF;
 
        for (int i=0; i<m; i++)
        {
            char ch;
            int temp[N], k = 0;
            while (true)
            {
                scanf ("%d%c", &temp[k++], &ch);
                if (ch == '\n') break;
            }
 
            for (int j=0; j<k; j++)
            {
                for (int k1=j; k1<k; k1++)
                {
                    int x1 = temp[j], y1 = temp[k1];
                    g[x1][y1] = 1;
                }
            }
        }
        dijkstra (n);
        if (dis[n] != INF) printf("%d\n", dis[n] - 1);
        else puts("NO");
    }
    return 0;
}
 
void dijkstra (int n)
{
    met (vis, 0); vis[1] = 1;
    for (int i=1; i<=n; i++)
        dis[i] = g[1][i];
 
    for (int i=0; i<=n; i++)
    {
        int u = 0, minx = INF;
        for (int j=0; j<=n; j++)
        {
            if (!vis[j] && minx > dis[j])
                u = j, minx = dis[j];
        }
        vis[u] = 1;
        for (int j=0; j<=n; j++)
        {
            if (!vis[j] && dis[j] > g[u][j] + dis[u])
                dis[j] = g[u][j] + dis[u];
        }
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值