洛谷 P1685 游览 解题报告

P1685 游览

题目描述

顺利通过了黄药师的考验,下面就可以尽情游览桃花岛了!

你要从桃花岛的西头开始一直玩到东头,然后在东头的码头离开。可是当你游玩了一次后,发现桃花岛的景色实在是非常的美丽!!!于是你还想乘船从桃花岛东头的码头回到西头,再玩一遍,但是桃花岛有个规矩:你可以游览无数遍,但是每次游玩的路线不能完全一样。

我们把桃花岛抽象成了一个图,共n个点代表路的相交处,m条边表示路,边是有向的(只能按照边的方向行走),且可能有连接相同两点的边。输入保证这个图没有环,而且从西头到东头至少存在一条路线。两条路线被认为是不同的当且仅当它们所经过的路不完全相同。

你的任务是:把所有不同的路线游览完一共要花多少时间?

输入输出格式

输入格式:

第1行为5个整数:n、m、s、t、t0,分别表示点数,边数,岛西头的编号,岛东头的编号(编号是从1到n)和你乘船从岛东头到西头一次的时间。

以下m行,每行3个整数:x、y、t,表示从点x到点y有一条行走耗时为t的路。

每一行的多个数据之间用一个空格隔开,且:2<=n<=10000; 1<=m<=50000;t<=10000;t0<=10000

输出格式:

假设总耗时为total,则输出total mod 10000的值(total对10000取余)。


题目不难,题意大概是统计所有路径的边权和。

因为是有向边,所以我们可以很方便的采用拓扑排序进行统计。

直接是加法原理和乘法原理上去就行了。

注意判掉自环,路径的方案数也要及时取膜(最开始没注意到只有60分)


Code:

#include <cstdio>
#include <queue>
#define ll long long
using namespace std;
const int N=10010;
const int M=50010;
const ll mod=10000;
int n,m,s,t,in[N];
int head[N],to[M],Next[M],cnt;
ll t0,edge[M],Cnt[N],len[N];
void add(int u,int v,ll w)
{
    to[++cnt]=v;Next[cnt]=head[u];edge[cnt]=w;head[u]=cnt;
}
void init()
{
    scanf("%d%d%d%d%lld",&n,&m,&s,&t,&t0);
    int u,v;ll w;
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%lld",&u,&v,&w);
        if(u!=v)
        {
            add(u,v,w);
            in[v]++;
        }
    }
}
queue <int > q;
void work()
{
    q.push(s);
    Cnt[s]=1;
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        for(int i=head[u];i;i=Next[i])
        {
            int v=to[i];ll w=edge[i];
            in[v]--;
            Cnt[v]=(Cnt[u]+Cnt[v])%mod;
            len[v]=((len[v]+len[u])%mod+w*Cnt[u]%mod)%mod;
            if(!in[v])
                q.push(v);
        }
    }
    ll ans=((Cnt[t]-1)*t0%mod+len[t])%mod;
    printf("%lld\n",ans);
}
int main()
{
    init();
    work();
    return 0;
}


2018.7.8

posted @ 2018-07-08 08:59  露迭月  阅读(195)  评论(0编辑  收藏  举报