比较简单的一场。
不过还是没有完成
A
K
AK
AK
最后一题把我做傻了,反正。因为没有看到
s
<
t
s<t
s<t,所以一直在想环没法做。
后来抛弃这个也没想出来,因为没看数据范围。
首先枚举边肯定是不行,但是我们发现可以尝试转换成点,这样复杂度就是
n
m
nm
nm
接近
n
3
n^3
n3,卡一卡还是可以的(数据也没出太满。
怎么转换成点呢,因为只删一条边,所以对于每个点的出边,我们判断另一端点期望最大的那个,把这条边断了,显然是最优的。
因为每条边都是由小的指向大的,所以甚至不需要拓扑序,直接倒序即可。
#include<bits/stdc++.h>
#define FOR(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn = 10050;
typedef long long ll;
int n,m;
double dp[maxn];
vector<int>G[maxn];
double slove(int p){
dp[n]=0;
for(int i=n-1;i>=1;i--){
int all=G[i].size();
if(!all||(i==p&&all==1)){dp[i]=0x3f3f3f3f;continue;};
double MAX=0,ret=0;
for(int j=0;j<all;j++){
MAX=max(dp[G[i][j]]+1,MAX);
ret+=1/double(all-(i==p))*(dp[G[i][j]]+1);
}
if(i==p)ret-=1/double(all-1)*MAX;
dp[i]=ret;
}
return dp[1];
}
int main(){
cin>>n>>m;
for(int i=1;i<=m;i++){
int s,t;
scanf("%d%d",&s,&t);
G[s].push_back(t);
}
double ans=slove(0);
for(int i=1;i<=n-1;i++){
ans=min(ans,slove(i));
}
printf("%.10f",ans);
}