记录编号 359798 评测结果 AAAAAAAAAA
题目名称 [NOI 2005]聪聪与可可 最终得分 100
用户昵称 GravatarFoolMike 是否通过 通过
代码语言 C++ 运行时间 0.121 s
提交时间 2016-12-24 21:46:16 内存使用 30.62 MiB
显示代码纯文本
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
typedef double db;
const int N=1010,M=10010;
int n,m,x,y,du[N],w[M],head[M],next[M],tail[M],cnt;
void add(int f,int t){
	w[++cnt]=t;du[f]++;
	if (!head[f]) head[f]=tail[f]=cnt;
		else tail[f]=next[tail[f]]=cnt;
}
db ans;
int f[N][N];
//dp[i][j][k]表示聪聪和可可分别在i,j位置
//k=0表示该可可走,k>0表示该聪聪走k步 
void spfa(int s){
	int *dis=f[s];
	for (int i=1;i<=n;i++) dis[i]=1e9;
	dis[s]=0;
	queue<int> Q;
	Q.push(s);
	while (!Q.empty()){
		int v=Q.front();Q.pop();
		for (int i=head[v];i;i=next[i])
		if (dis[w[i]]>dis[v]+1)
			dis[w[i]]=dis[v]+1,Q.push(w[i]);
	}
}
bool vis[N][N][3];db dp[N][N][3];
db p(int x,int y,int k){//返回dp[x][y][k]的值 
	if (x==y) return 0;
	if (vis[x][y][k]) return dp[x][y][k];
	vis[x][y][k]=1;
	db ans=0;
	if (!k){
		db P=1.0/(du[y]+1);
		ans+=(1+p(x,y,2))*P;
		for (int i=head[y];i;i=next[i])
		if (x!=w[i]) ans+=(1+p(x,w[i],2))*P;
	}else
	if (k==1){
		int d=f[x][y]-1,pos=n;
		for (int i=head[x];i;i=next[i]){
			int v=w[i];
			if (f[v][y]==d) pos=min(v,pos);
		}
		ans+=p(pos,y,0);
	}else
	if (k==2){
		int d=f[x][y]-1,pos=n;
		for (int i=head[x];i;i=next[i]){
			int v=w[i];
			if (f[v][y]==d) pos=min(v,pos);
		}
		ans+=p(pos,y,1);
	}
	return dp[x][y][k]=ans;
}
int main()
{
	freopen("cchkk.in","r",stdin);
	freopen("cchkk.out","w",stdout);
	scanf("%d%d%d%d",&n,&m,&x,&y);
	for (int i=1;i<=n;i++)
	for (int j=1;j<=n;j++)
	if (i!=j) f[i][j]=1e9;
	for (int i=1;i<=m;i++){
		int u,v;
		scanf("%d%d",&u,&v);
		add(u,v);add(v,u);
	}
	for (int i=1;i<=n;i++) spfa(i);
	printf("%.3lf\n",x!=y?1+p(x,y,2):0);
	return 0;
}