ZOJ 3088 最短路 最长路

做一个最短路 一个最长路,枚举两点求比值最大的记录,然后最后输出就行

#include <set>
#include <map>
#include <cmath>
#include <queue>
#include <stack>
#include <string>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

typedef  long long LL;
const double PI = acos(-1.0);

template <class T> inline  T MAX(T a, T b){if (a > b) return a;return b;}
template <class T> inline  T MIN(T a, T b){if (a < b) return a;return b;}

const int N = 111;
const int M = 11111;
const LL MOD = 1000000007LL;
const int dir[4][2] = {1, 0, -1, 0, 0, -1, 0, 1};
const int INF = 0x3f3f3f3f;


int dist[1111][1111];
int down[1111][1111];
int path1[1111][1111];
int path2[1111][1111];
struct node
{
    int v, w, next;
}edge[2222], redge[2222];
int head1[1111], head2[1111], cnt1, cnt2;
int n, m1, m2, inq[1111];



inline void addnode1(int u, int v, int w)
{
    edge[cnt1].v = v; edge[cnt1].w = w;
    edge[cnt1].next = head1[u]; head1[u] = cnt1++;
}

inline void addnode2(int u, int v, int w)
{
    redge[cnt2].v = v; redge[cnt2].w = w;
    redge[cnt2].next = head2[u]; head2[u] = cnt2++;
}


void spfa1(int d[], int v0)
{
    fill(d, d + n + 1, -1);
    memset(inq, 0, sizeof(inq));
    queue < int > q;
    q.push(v0);
    inq[v0] = 1; d[v0] = 0;
    path1[v0][v0] = -1;
    int u, v, i, j, k, w;
    while (!q.empty())
    {
        u = q.front(); q.pop(); inq[u]--;
        for (i = head1[u]; ~i; i = edge[i].next)
        {
            v = edge[i].v; w = edge[i].w;
//            if (v == v0) continue;
            if (d[u] + w > d[v])
            {
                d[v] = d[u] + w;
                path1[v0][v] = u;
                if (!inq[v]) {inq[v]++; q.push(v);}
            }
        }
    }
}


void spfa2(int d[], int v0)
{
    fill(d, d + n + 1, INF);
    memset(inq, 0, sizeof(inq));
    queue < int > q;
    q.push(v0);
    path2[v0][v0] = -1;
    inq[v0] = 1; d[v0] = 0;
    int u, v, i, j, k, w;
    while (!q.empty())
    {
        u = q.front(); q.pop(); inq[u]--;
        for (i = head2[u]; ~i; i = redge[i].next)
        {
            v = redge[i].v; w = redge[i].w;
//            if (v == v0) continue;
            if (d[u] + w < d[v])
            {
                d[v] = d[u] + w;
                path2[v0][v] = u;
                if (!inq[v]) {inq[v]++; q.push(v);}
            }
        }
    }
}

void output1(int p, int k)
{
    if (path2[p][k] != -1)
    {
        output1(p, path2[p][k]);
    }
    printf("%d ", k);
}

void output2(int p, int k)
{
    if (path1[p][path1[p][k]] != -1)
    {
        output2(p, path1[p][k]);
    }
    if (path1[p][path1[p][k]] == -1) printf("%d", k);
    else printf(" %d", k);
}



int main()
{
    int T;
    scanf("%d", &T);
    while (T--)
    {
        int i,j ,k, u, v, w;
        memset(head1, -1, sizeof(head1));
        cnt1 = cnt2 = 0;
        memset(head2, -1, sizeof(head2));
        scanf("%d%d%d", &n, &m1, &m2);
        for (i = 0; i < m1; ++i)
        {
            scanf("%d%d%d", &u, &v, &w);
            addnode1(u, v, w);
        }
        for (i = 0; i < m2; ++i)
        {
            scanf("%d%d%d", &u, &v, &w);
            addnode2(u, v, w);
        }
        for (i = 1; i <= n; ++i)
        {
            spfa1(down[i], i);
            spfa2(dist[i], i);
        }
        int pos1, pos2;
        double mm = 0;
        for (i = 1; i <= n; ++i)
            for (j = 1; j <= n; ++j)
            {
                if (down[j][i] != -1 && dist[i][j] != INF && i != j)
                {
                    if (1.0 * (down[j][i]) / dist[i][j] > mm)
                    {
                        pos1 = i; pos2 = j; mm = 1.0 * (down[j][i]) / dist[i][j];
                    }
                }
            }
//        for (i = 1; i <= n; ++i)
//        {
//            for (j = 1; j <= n; ++j)
//                printf("%d ", dist[i][j]);
//            printf("\n");
//        }
        output1(pos1, pos2);
        output2(pos2, pos1);
        printf("\n%.3f\n", mm);
    }
    return 0;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值