潜行世界
- 总时间限制:
- 10000ms
- 内存限制:
- 256000kB
- 描述
-
HJA和学弟还在旅游中,这次他们来到了潜行世界。潜行世界是一个N个点M条边的有向无环图。每条路对于HJA和学弟都一个吸引指数,我们把它叫做这条边的权值。权值越大,HJA和学弟就越有可能走这条路。假设HJA和学弟现在在点u,点u出发的所有边的权值之和为s,从u到v的边的权值为w,那么他们选择走向v的概率就是。为了使得问题变得更加简单,HJA决定在开始前删掉任意一条边(也可以不删)。当HJA和学弟走到一个没有出边的点时,这次旅行就结束了。HJA想知道,如果他和学弟从零号点出发,他们期望走的长度最长是多少呢?(每条边的长度都为1)
- 输入
- 第一行两个正整数N、M,代表图的点数和边数。
接下来M行每行三个整数S、E、D,代表S到E有一条权值为D的边。 - 输出
- 一行一个实数代表答案,误差不得超过1e-6。(没有spj,有问题就找zhx)
- 样例输入
-
4 5 0 1 2 0 2 1 0 3 3 1 3 1 2 3 4
- 样例输出
-
2.000000
- 提示
- 对于50%的数据,1≤N≤500。
对于100%的数据,1≤N≤10,000,1≤M≤100,000,所有边权不超过103。 - 来源
- zhonghaoxi
- 這道題在考場上將無向圖與樹搞混了,用樹形DP的思路來做得這道題,上述思路會出現算重的問題。
- 這道題的正解是預處理計算到每個點的概率,在枚舉刪邊。
-
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<ctime> #include<cmath> #include<algorithm> #include<set> #include<map> #include<vector> #include<string> #include<queue> using namespace std; #ifdef WIN32 #define LL "%I64d" #else #define LL "%lld" #endif #define MAXN 110000 #define MAXV MAXN*2 #define MAXE MAXV*2 #define INF 0x3f3f3f3f #define INFL 0x3f3f3f3f3f3f3f3fLL #define PROB "secretbase" typedef long long qword; inline int nextInt() { char ch; int x=0; bool flag=false; do ch=getchar(),flag=(ch=='-')?true:flag; while(ch<'0'||ch>'9'); do x=x*10+ch-'0'; while (ch=getchar(),ch<='9' && ch>='0'); return x*(flag?-1:1); } int n,m; struct Edge { int np,val; Edge *next; }E[MAXN],*V[MAXV]; int tope=-1; void addedge(int x,int y,int z) { E[++tope].np=y; E[tope].val=z; E[tope].next=V[x]; V[x]=&E[tope]; } int totw[MAXN]; int el[MAXE][3]; bool vis[MAXN]; queue<int> Q; int seq[MAXN],tops=-1; int dego[MAXN]; int degi[MAXN]; double poss[MAXN],g[MAXN];; int main() { freopen(PROB".in","r",stdin); freopen(PROB".out","w",stdout); int i,j,k; int x,y,z; scanf("%d%d",&n,&m); for (i=0;i<m;i++) { scanf("%d%d%d",&x,&y,&z); totw[x]+=z; addedge(x,y,z); dego[x]++; degi[y]++; el[i][0]=x; el[i][1]=y; el[i][2]=z; } memset(vis,0,sizeof(vis)); for (i=0;i<n;i++) { if (!degi[i]) { Q.push(i); vis[i]=true; } } int now; Edge *ne; while (!Q.empty()) { now=Q.front(); Q.pop(); seq[++tops]=now; for (ne=V[now];ne;ne=ne->next) { if (vis[ne->np])continue; degi[ne->np]--; if (!degi[ne->np]) { Q.push(ne->np); vis[ne->np]=true; } } } poss[0]=1; for (i=0;i<=tops;i++) { now=seq[i]; for (ne=V[now];ne;ne=ne->next) { poss[ne->np]+=poss[now]*ne->val/totw[now]; } } tope=-1; memset(V,0,sizeof(V)); memset(vis,0,sizeof(vis)); for (i=0;i<n;i++)g[i]=1e100; for (i=0;i<m;i++) { addedge(el[i][1],el[i][0],el[i][2]); } for (i=0;i<n;i++) { if (!dego[i]) { vis[i]=true; Q.push(i); g[i]=0; } } tops=-1; while (!Q.empty()) { now=Q.front(); Q.pop(); seq[++tops]=now; for (ne=V[now];ne;ne=ne->next) { if (vis[ne->np])continue; dego[ne->np]--; if (!dego[ne->np]) { Q.push(ne->np); vis[ne->np]=true; } } } // for (i=0;i<=tops;i++)printf("%d ",seq[i]);printf(" "); memset(V,0,sizeof(V)); tope=-1; for (i=0;i<m;i++) { addedge(el[i][0],el[i][1],el[i][2]); } for (i=0;i<=tops;i++) { now=seq[i]; if (!g[now])continue; g[now]=0; for (ne=V[now];ne;ne=ne->next) { g[now]+=g[ne->np]*ne->val/totw[now]; } g[now]+=1; } // for (i=0;i<n;i++)printf("%lf ",g[i]); double delta=-1e100; double t; double gn; for (i=0;i<m;i++) { if (totw[el[i][0]]==el[i][2]) { gn=0; }else gn=(g[el[i][0]]-(g[el[i][1]]+1)*el[i][2]/totw[el[i][0]])*totw[el[i][0]]/(totw[el[i][0]]-el[i][2]); delta=max((gn-g[el[i][0]])*poss[el[i][0]],delta); } delta=max(0.0,delta); printf("%.6lf ",g[0]+delta); return 0; }