洛谷 P2656 采蘑菇
来源:互联网 发布:淘宝回购率什么意思 编辑:程序博客网 时间:2024/05/17 07:32
题目描述 Description
小胖和ZYR要去ESQMS森林采蘑菇。
ESQMS森林间有N个小树丛,M条小径,每条小径都是单向的,连接两个小树丛,上面都有一定数量的蘑菇。小胖和ZYR经过某条小径一次,可以采走这条路上所有的蘑菇。由于ESQMS森林是一片神奇的沃土,所以一条路上的蘑菇被采过后,又会长出一些新的蘑菇,数量为原来蘑菇的数量乘上这条路的“恢复系数”,再下取整。
比如,一条路上有4个蘑菇,这条路的“恢复系数”为0.7,则第一~四次经过这条路径所能采到的蘑菇数量分别为4,2,1,0.
现在,小胖和ZYR从S号小树丛出发,求他们最多能采到多少蘑菇。
对于30%的数据,N<=7,M<=15
另有30%的数据,满足所有“恢复系数”为0
对于100%的数据,N<=80,000,M<=200,000,0.1<=恢复系数<=0.8且仅有一位小数,1<=S<=N.
输入输出格式 Input/output
输入格式:
第一行,N和M
第2……M+1行,每行4个数字,分别表示一条小路的起点,终点,初始蘑菇数,恢复系数。
第M+2行,一个数字S
输出格式:
一个数字,表示最多能采到多少蘑菇,在int32范围内。
输入样例:
3 3
1 2 4 0.5
1 3 7 0.1
2 3 4 0.6
1
输出样例:
8
今天的最后一道强连通题……
不知道什么原因脑子一直抽风,在一些很无聊的地方犯傻…………
题目蛮明确的,对于每条路来说,多经过几次就有可能有更高的收益,但因为是单向边,如果某条路经过多次的话,那么就必定是有环了,优先把这个环上的点都走一遍得到的答案一定更优一些,所以对于每个环,把它处理一遍之后缩成一个点,其权值为在上面把该环上的点全跑成0得到的最大值
想法蛮简单,实现起来蛮恶心的…………
#include<iostream>#include<cstdio>#include<queue>#include<cstring>#include<stack>#define FUCKCY 12using namespace std;const int maxn=2333333;struct doubi{ int f,t,d; double u;}edge[maxn];int next[maxn],first[maxn],tot;void build(int f,int t,int d,double u){ edge[++tot].f=f; edge[tot].t=t; edge[tot].d=d; edge[tot].u=u; next[tot]=first[f]; first[f]=tot;}int pre[maxn];stack<int> q;int cnt;int scc_num[maxn];int scc_cnt;int n,m;int vlaue[maxn];int fa[maxn];int tarjan(int u){ int lowu=pre[u]=++cnt; q.push(u); for(int i=first[u];i;i=next[i]){ int v=edge[i].t; if(!pre[v]){ int lowv=tarjan(v); lowu=min(lowu,lowv); } else if(!scc_num[v]){ lowu=min(lowu,pre[v]); } } if(lowu==pre[u]){ scc_cnt++; fa[scc_cnt]=u; while(FUCKCY){ int v=q.top(); q.pop(); scc_num[v]=scc_cnt; if(u==v){ break; } } } return lowu;//忘打了,死在这里了……QAQ }queue<int> w;bool vis[maxn];int getv(doubi a){ int temp=0; int temp1=a.d; double temp2=a.u; while(temp1){ temp+=temp1; temp1*=temp2; } return temp;}void bfs(int u,int cnt){ for(int i=first[u];i;i=next[i]){ int v=edge[i].t; if(scc_num[v]==cnt){ vlaue[cnt]+=getv(edge[i]); if(!vis[v]){ vis[v]=1; bfs(v,cnt); } } }}void getvlaue(){ for(int i=1;i<=scc_cnt;i++){//其实这里直接枚举点就好,没必要记录这个数组的 vis[fa[i]]=1; bfs(fa[i],i); }}struct faq{ int f,t,d;}newedge[maxn];int newnext[maxn],newfirst[maxn],newtot;void build_new(int f,int t,int d){ newedge[++newtot].f=f; newedge[newtot].t=t; newedge[newtot].d=d; newnext[newtot]=newfirst[f]; newfirst[f]=newtot;}int s;long long dist[maxn];bool use[maxn];void spfa(){ for(int i=1;i<=scc_cnt;i++){ dist[i]=-2147483647777ll; } dist[scc_num[s]]=vlaue[scc_num[s]];//不要忘了把处理出来的scc的权值加上…… use[scc_num[s]]=1; w.push(scc_num[s]); while(!w.empty()){ int u=w.front(); w.pop(); use[u]=0; for(int i=newfirst[u];i;i=newnext[i]){ int v=newedge[i].t; if(dist[v]<dist[u]+newedge[i].d+vlaue[v]){ dist[v]=dist[u]+newedge[i].d+vlaue[v]; if(!use[v]){ use[v]=1; w.push(v); } } } }}int main(){ cin>>n>>m; for(int i=1;i<=m;i++){ int a,b,c; double x; scanf("%d%d%d%lf",&a,&b,&c,&x);//把那个系数直接存到边里 build(a,b,c,x); } for(int i=1;i<=n;i++){ if(!pre[i]){ tarjan(i);//求scc } } getvlaue();//处理每个scc的权值 for(int i=1;i<=m;i++){ int f=edge[i].f,t=edge[i].t; if(scc_num[f]!=scc_num[t]){ build_new(scc_num[f],scc_num[t],edge[i].d);//缩点 } } cin>>s; spfa();//最长路 int ans=0; for(int i=1;i<=scc_cnt;i++){ ans=max((long long)ans,dist[i]); } cout<<ans<<endl; return 0;}
- 洛谷 P2656 采蘑菇
- 【洛谷 P2656】采蘑菇
- 洛谷P2656 采蘑菇
- 洛谷 P2656 采蘑菇
- 洛谷P2656 采蘑菇
- 洛谷P2656 采蘑菇
- 【洛谷 P2656】采蘑菇
- 洛谷 P2656 采蘑菇(Tarjan)
- 洛谷2656 采蘑菇
- 洛谷2656 采蘑菇
- 【洛谷 2656】采蘑菇
- 采蘑菇
- 采蘑菇
- qduoj GZS采蘑菇
- [JZOJ5058]采蘑菇
- BOJ 478 小妹妹采蘑菇
- boj478. 小妹妹采蘑菇-概率
- c++游戏设计四:采蘑菇
- iOS 计算某个时间距今天的天数
- poj-3624Charm Bracelet
- 今天把吃饭的家伙又清洗了一遍
- Python基础(二) Python常用变量
- ARM9开发板FL2440移植Linux-3.0内核————MMC和LCD驱动
- 洛谷 P2656 采蘑菇
- 洛谷 1993 小 K 的农场
- BZOJ****-****
- Android APP引导页制作
- Python基础(三) Python字符串
- JQUERY获取当前页面的URL信息
- phpstorm
- 创业漫话八(有效率的公司组织下)
- matlab与c++混合编程