题目1100:最短路径

/********
用向量存2的幂所构成的多项式的位权,在多项式运算时用到操作符的重载
********/
#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 105;

typedef long long LL;

int n, m;
int g[N][N];
vector<int> dis[N];
bool vis[N];

void dijkstra();
vector<int> operator + (vector<int> v, int data);
bool operator < (vector<int> v1, vector<int>v2);
LL exp(LL a, LL b, LL m);

int main()
{
    #ifndef ONLINE_JUDGE
        freopen("d:\\OJ\\uva_in.txt", "r", stdin);
    #endif // ONLINE_JUDGE

    while (scanf("%d%d", &n, &m) == 2) {
        memset(g, -1, sizeof(g));
        for (int i = 0; i < m; i++) {
            int a, b;
            scanf("%d%d", &a, &b);
            g[a][b] = g[b][a] = i;
        }
        dijkstra();
    }
    return 0;
}

vector<int> operator + (vector<int> v, int data)
{
    vector<int> ans;

    sort(v.begin(), v.end());

    for (int i = 0; i < v.size(); i++) {
        if (v[i] == data) {
            v[i]++;
            ans = v;
            return ans;
        }
    }

    ans = v;
    ans.push_back(data);
    return ans;
}

bool operator < (vector<int> v1, vector<int>v2)
{
    sort(v1.begin(), v1.end());
    sort(v2.begin(), v2.end());

    vector<int>::iterator it1 = v1.end(), it2 = v2.end();
    it1--, it2--;

    while (it1 != v1.begin() && it2 != v2.begin()) {
        if (*it1 < *it2) return true;
        else if (*it1 > *it2) return false;
        else {
            it1--, it2--;
        }
    }

    if (*it1 == *it2) {
        return v1.size() < v2.size();
    }

    return *it1 < *it2;
}

void dijkstra()
{
    memset(vis, false, sizeof(vis));

    for (int i = 0; i < n; i++) {
        dis[i].clear();
        dis[i].push_back(1000);
    }

    for (int i = 0; i < n; i++) {
        if (g[0][i] != -1) {
            dis[i].clear();
            dis[i].push_back(g[0][i]);
        }
    }

    vis[0] = true;
    int u = 0;

    for (int i = 1; i < n; i++) {
        vector<int> Min;
        Min.push_back(1000);

        for (int j = 0; j < n; j++) {
            if (!vis[j] && dis[j] < Min) {
                Min = dis[j];
                u = j;
            }
        }

        vis[u] = 1;

        for (int j = 0; j < n; j++) {
            if (!vis[j] && g[u][j] != -1 && dis[u] + g[u][j] < dis[j]) {
                dis[j] = dis[u] + g[u][j];
            }
        }
    }

    for (int i = 1; i < n; i++) {
        if (dis[i].size() == 1 && dis[i][0] == 1000) {
            printf("-1\n");
            continue;
        }

        LL len = 0;
        for (int j = 0; j < dis[i].size(); j++) {
            len += exp(2, dis[i][j], 100000);
            len %= 100000;
        }
        printf("%lld\n", len);
    }
}

LL exp(LL a, LL b, LL m)
{
    LL product = 1;

    while (b) {
        if (b & 1) product = product * a % m;

        a = a * a % m;

        b >>= 1;
    }

    return product;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kgduu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值