题目描述
顺利通过了黄药师的考验,下面就可以尽情游览桃花岛了!
你要从桃花岛的西头开始一直玩到东头,然后在东头的码头离开。可是当你游玩了一次后,发现桃花岛的景色实在是非常的美丽!!!于是你还想乘船从桃花岛东头的码头回到西头,再玩一遍,但是桃花岛有个规矩:你可以游览无数遍,但是每次游玩的路线不能完全一样。
我们把桃花岛抽象成了一个图,共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取余)。
输入输出样例
3 4 1 3 71 2 52 3 72 3 101 3 15
56
说明
【样例说明】
共有3条路径可以从点1到点3,分别是1-2-3,1-2-3,1-3。
时间计算为:
(5+7)+7 +(5+10)+7 +(15)=56
解:
暴力:
爆搜所有的路线,40分
正解:加法原理+乘法原理
设sum[i]为从起点出发到达i的方案数
len[i]为为从起点出发到达i的路径总和
考虑一条边i -> j ,花费时间为t
那么则有:
len[j]=len[j]+len[i]+t*sum[i];
sum[j]=sum[j]+sum[i]
对于起点S:sum[S]=1;
注意题目中给的性质:
“输入保证这个图没有环,而且从西头到东头至少存在一条路线”
于是我们可以利用拓扑排序来进行这一工作,得到
sum[i]和len[i].
我们也可以建反向边,从T开始出发去找,进行DFS,
从而得到sum[i]和len[i]
代码:
1.拓扑排序做法
1 #include<algorithm> 2 #include<iostream> 3 #include<cstdio> 4 #include<cstring> 5 #include<string> 6 #include<queue> 7 #include<cmath> 8 #define ll long long 9 #define DB double10 #define mod 1000011 #define eps 1e-312 #define inf 214748360013 using namespace std;14 inline int read()15 {16 ????int x=0,w=1;char ch=getchar();17 ????while(ch<‘0‘ || ch>‘9‘){if(ch==‘-‘) w=-1;ch=getchar();}18 ????while(ch>=‘0‘ && ch<=‘9‘) x=(x<<3)+(x<<1)+ch-‘0‘,ch=getchar();19 ????return x*w;20 }21 const int N=1e6+10;22 struct node{23 ????int u,v,c,ne;24 }e[N];25 int h[N],tot,v[N],d[N];26 void add(int u,int v,int c)27 {28 ????d[v]++;29 ????tot++;e[tot]=(node){u,v,c,h[u]};h[u]=tot;30 }31 int n,m,S,T,t0,sum[N],len[N];32 queue<int>q;33 void tuopu()34 {35 ????sum[S]=1;36 ????for(int i=1;i<=n;++i) 37 ?????if(d[i]==0) q.push(i);38 ????while(!q.empty())39 ????{40 ????????int ff=q.front();q.pop();41 ????????for(int i=h[ff];i;i=e[i].ne)42 ????????{43 ????????????int rr=e[i].v;44 ????????????d[rr]--;45 ????????????sum[rr]=(sum[rr]+sum[ff])%mod;46 ????????????len[rr]=(len[rr]+len[ff]+e[i].c*sum[ff]%mod)%mod;47 ????????????if(d[rr]==0) q.push(rr);48 ????????}49 ????}50 }51 int main()52 {53 ????n=read();m=read();S=read();T=read();t0=read();54 ????for(int i=1;i<=m;++i)55 ????{56 ????????int x,y,z;x=read();y=read();z=read();57 ????????add(x,y,z);58 ????}59 ????tuopu();60 ????ll ans=0;61 ????ans=(len[T]+(sum[T]-1)*t0%mod)%mod;62 ????printf("%lld",(ans+mod)%mod);63 ????return 0;64 }
2.DFS做法
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cmath> 5 #include<cstring> 6 #include<map> 7 #include<queue> 8 #define mod 10000 9 #define inf 33686018010 #define PI 3.141592611 #define ll long long12 using namespace std;13 int n,m,s,t,t0,h[100000],tot,ans,sum[100000],len[100000];14 struct po{int v,c,last;}a[500000];15 void add(int u,int v,int c)16 {17 ????tot++;18 ????a[tot].v=v;a[tot].c=c;19 ????a[tot].last=h[u];h[u]=tot;20 }21 bool v[1000000];22 void dfs(int x)23 {24 ????if(v[x]) return ;25 ????v[x]=1;26 ????if(x==s)27 ????{28 ????????sum[x]=1;len[x]=0;29 ?????????return;30 ????}31 ????int sumx=0,lenx=0;32 ????for(int i=h[x];i;i=a[i].last)33 ????{34 ?????int to=a[i].v;35 ?????dfs(to);36 ?????lenx=(lenx+a[i].c*sum[to]+len[to])%mod;37 ?????sumx=(sumx+sum[to])%mod;38 ????}39 ????sum[x]=sumx;len[x]=lenx;40 }41 int main()42 {43 ????scanf("%d%d%d%d%d",&n,&m,&s,&t,&t0);44 ????for(int i=1;i<=m;i++)45 ????{46 ?????int x,y,t;scanf("%d%d%d",&x,&y,&t);47 ?????add(y,x,t); ???48 ????}49 ????dfs(t);50 ????ans=(mod+len[t]+(sum[t]-1)*t0%mod)%mod;51 ????cout<<ans;52 ????return 0;53 }
(?′?‵?)I L???????
JSOI2007夏令营考试游览
原文地址:https://www.cnblogs.com/adelalove/p/8494021.html