拓扑排序+数学+DP【洛谷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取余)。

拓扑排序+DP+数学 乘法原理搞一搞就行了 不知道这题怎么被刷成紫色的。。。

code:

#include <iostream>
#include <cstdio>
#include <queue>

#define int long long

using namespace std;

const int wx=100017;
const int mod=10000;

inline int read(){
	int sum=0,f=1; char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
	while(ch>='0'&&ch<='9'){sum=(sum<<1)+(sum<<3)+ch-'0'; ch=getchar();}
	return sum*f;
}

int num,n,m,s,t,t0;
int f[wx],g[wx],in[wx],head[wx];

struct e{
	int nxt,to,dis;
}edge[wx*2];

void add(int from,int to,int dis){
	edge[++num].nxt=head[from];
	edge[num].to=to;
	edge[num].dis=dis;
	head[from]=num;
}

queue<int > q;
void bfs(){
	q.push(s); g[s]=1;
	while(q.size()){
		int u=q.front(); q.pop();
		for(int i=head[u];i;i=edge[i].nxt){
			int v=edge[i].to;
			(f[v]+=f[u]+g[u]*edge[i].dis)%=mod;
			(g[v]+=g[u])%=mod;
			in[v]--;
			if(!in[v])q.push(v);
		}
	}
}

signed main(){
	n=read(); m=read(); s=read(); t=read(); t0=read();
	for(int i=1;i<=m;i++){
		int x,y,z;
		x=read(); y=read(); z=read();
		if(x==y)continue;
		in[y]++;
		add(x,y,z);
	}
	bfs();
	printf("%lld
",(f[t]%mod+(g[t]-1)*t0%mod)%mod);
	return 0;
}
原文地址:https://www.cnblogs.com/wangxiaodai/p/9805872.html