题目链接
给一张无向连通图,要求给m条边中的每条边一个1~m的权值使得从1号点到n号点的期望最小
选择边的概率相等
走到n就停止
n≤500 n ≤ 500
DP? 这是个无向连通图,似乎不好DP
做这种题先把题目要求的式子给写出来:
好像无从下手,因为枚举路径是不可做的
显然的我们可以考虑每一条边对答案的贡献,就是:
这样还是不好处理,但已经可以看出贪心策略了,不妨先假设每一条边的权值都为1,然后算出下面那一坨东西排序,再依次赋权值即可
注意到此时边的贡献可以转化为边两头点贡献的和,就是:
E(i) E ( i ) 表示边i的贡献(边权是1), P(u) P ( u ) 表示走到了 u u 点的概率
由于有环不能递推,但是可以列方程,然后高斯消元
列方程比较简单,只是有几个细节罢了,自己YY吧
代码:
#include
#include
#include
#include
#include
#include
#include
using namespace std;
inline int read()
{
int x=0;char ch=getchar();int t=1;
for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') t=-1;
for(;ch>='0'&&ch<='9';ch=getchar()) x=(x<<1)+(x<<3)+(ch-48);
return x*t;
}
typedef long long ll;
typedef double db;
const int N=501;
db du[N];
struct edge{
int to,next;
}A[(N*N)<<1];
int n,m;
int head[N];int cnt=0;
inline void add(int x,int y){A[++cnt]=(edge){y,head[x]};head[x]=cnt;}
db a[N][N];
db P[N];
const db eps=1e-12;
struct ED{
int u,v;db val;
inline bool operator <(ED b)const{
return val>b.val;
}
}B[N*N];
inline void Gauss_Jordan()
{
for(register int h=1;h<=n;++h){
register int p=h;
for(register int i=h+1;i<=n;++i){
if(fabs(a[i][h])<=eps) continue;
if(fabs(a[i][h])>fabs(a[p][h])) p=i;
}
if(p!=h) swap(a[p],a[h]);
register db t=a[h][h];
for(register int i=h;i<=n+1;++i) a[h][i]/=t;
for(register int i=1;i<=n;++i){
if(i==h||fabs(a[i][h])<=eps) continue;
t=a[i][h];
for(register int j=h;j<=n+1;++j) a[i][j]=(a[i][j]-a[h][j]*t);
}
}
for(register int i=1;i<=n;++i) P[i]=a[i][n+1];
return;
}
int main()
{
register int u,v;
n=read();m=read();
for(register int i=1;i<=m;++i){
u=read();v=read();
++du[u];++du[v];B[i].u=u;B[i].v=v;
add(u,v);add(v,u);
}
for(register int u=1;u<=n;++u){
a[u][u]=1.00;a[u][n+1]=0.0;
for(register int v,i=head[u];i;i=A[i].next){
v=A[i].to;
if(v!=n) a[u][v]+=(-1.00/du[v]);
}
}
a[1][n+1]=1.00;
Gauss_Jordan();
for(register int i=1;i<=m;++i){
if(B[i].u!=n) B[i].val+=P[B[i].u]/du[B[i].u];
if(B[i].v!=n) B[i].val+=P[B[i].v]/du[B[i].v];
}
sort(B+1,B+1+m);
db head=0;register db ans=0;
for(register int i=1;i<=m;++i){
++head;ans+=head*B[i].val;
}
printf("%.3lf\n",ans);
return 0;
}