洛谷 P1231 教辅的组成(最大流) 题解

题目来源:

https://www.luogu.org/problemnew/show/P1231

题目描述:

 

题目背景

狗哥做烂了最短路,突然机智的考了Bosh一道,没想到把Bosh考住了...你能帮Bosh解决吗?

他会给你100000000000000000000000000000000000%10金币w

题目描述

给定n个点的带权有向图,求从1到n的路径中边权之积最小的简单路径。

输入输出格式

输入格式:

第一行读入两个整数n,m,表示共n个点m条边。 接下来m行,每行三个正整数x,y,z,表示点x到点y有一条边权为z的边。

输出格式:

输出仅包括一行,记为所求路径的边权之积,由于答案可能很大,因此狗哥仁慈地让你输出它模9987的余数即可。

废话当然是一个数了w

//谢fyszzhouzj指正w

对于20%的数据,n<=10。

对于100%的数据,n<=1000,m<=1000000。边权不超过10000。

输入输出样例

输入样例#1: 复制

3 3
1 2 3 
2 3 3 
1 3 10

输出样例#1: 复制

9

说明

好好看一看再写哟w

解题思路:

         这题是最短路的变形,感觉不错,因为求的是积的最小值,不是和的最小值,关键还要取模,在松弛的时候取模显然会导致贪心失败,我们可以考虑log(n*m)=log(n)+log(m),我们将边权都取对数,然后跑一遍spfa并记录下路径,然后在通过路径进行计算结果取模。。。感觉思路不错。

代码:

#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
#include<stack>
#include<vector>
#include<cmath>
#include<cstdio>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
const int maxn=1e6+10;
const int mod=9987;
struct newt
{
    int to,next;
    double val;
}e[maxn];
int n,cnt,m,vis[1010],head[1010],tu[1010][1010],pre[1010];
double dis[1010];
void addedge(int u,int v,double w)
{
    e[cnt].to=v;
    e[cnt].val=w;
    e[cnt].next=head[u];
    head[u]=cnt++;
}
int main()
{

    memset(head,-1,sizeof(head));
    cnt=0;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n+1;i++)
        dis[i]=1e9;
    for(int i=1;i<=m;i++)
    {
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        tu[a][b]=c;
        double w= log (c);
        addedge(a,b,w);

    }

    queue<int>q;
    vis[1]=1;
    q.push(1);
    dis[1]=0;
    while(!q.empty())
    {
        int now=q.front();
        q.pop();
        vis[now]=0;
        for(int i=head[now];i!=-1;i=e[i].next)
        {
            int v=e[i].to;
            if(dis[v]>dis[now]+e[i].val)
            {
                dis[v]=dis[now]+e[i].val;
                pre[v]=now;
                if(!vis[v])
                {
                    vis[v]=1;
                    q.push(v);
                }
            }
        }
    }
    ll ans=1;
    int t=n;
    while(t!=1)
    {
        ans=1ll*(ans%mod)*(tu[pre[t]][t]%mod);
        while(ans>mod)ans-=mod;
        t=pre[t];
    }
    printf("%lld\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40400202/article/details/81433249