Walk
Time Limit: 30000/15000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 361 Accepted Submission(s): 234
Special Judge
The nation looks like a connected bidirectional graph, and I am randomly walking on it. It means when I am at node i, I will travel to an adjacent node with the same probability in the next step. I will pick up the start node randomly (each node in the graph has the same probability.), and travel for d steps, noting that I may go through some nodes multiple times.
If I miss some sights at a node, it will make me unhappy. So I wonder for each node, what is the probability that my path doesn't contain it.
For each test case, the first line contains 3 integers n, m and d, denoting the number of vertices, the number of edges and the number of steps respectively. Then m lines follows, each containing two integers a and b, denoting there is an edge between node a and node b.
T<=20, n<=50, n-1<=m<=n*(n-1)/2, 1<=d<=10000. There is no self-loops or multiple edges in the graph, and the graph is connected. The nodes are indexed from 1.
Your answer will be accepted if its absolute error doesn't exceed 1e-5.
2 5 10 100 1 2 2 3 3 4 4 5 1 5 2 4 3 5 2 5 1 4 1 3 10 10 10 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 4 9
0.0000000000 0.0000000000 0.0000000000 0.0000000000 0.0000000000 0.6993317967 0.5864284952 0.4440860821 0.2275896991 0.4294074591 0.4851048742 0.4896018842 0.4525044250 0.3406567483 0.6421630037
题意:给一个n个点,m条边的双向联通图,旅行者要旅行d 天,旅行者随机选择起点,也就是说每个点选择的概率相等。旅行者下一天会随机的去与当前点相邻的一个点(所谓相邻的点就是与该点有一条直接相连的边),求d天旅行者没有访问第K个点的概率。
题解:目标状态为d天后没有访问第K个点,用dp[ i ][ j ]表示第i天,旅行者在点j,前i-1天没有访问过点K,要到达目标状态的概率。转移为:
dp[ i ] [ j ]=sum( 1/b * dp[ w ][ j+1 ] )。b表示与点i相邻的点的个数,w为与点 i 相邻的点。我们可以用记忆化搜索的方式实现转移。这个方法可以过,但是理论复杂度偏高。
由于N只有50,正解是用矩阵实现转移。由状态转移方程,我们可以这样构造矩阵,假设图为这样时:
n=4,m=4,边如下:
1 2
2 3
3 4
2 4
构造矩阵A如下:
0 1 0 0
1/3 0 1/3 1/3
0 1/2 0 1/2
0 1/2 1/2 0
假设K等于3,构造初始矩阵B
1
1
0
1
设矩阵C为
dp [ 1 ] [ 1 ]
dp [ 1 ] [ 2 ]
dp [ 1 ] [ 3 ]
dp [ 1 ] [ 4 ]
那么C=B*(A)^d。
复杂度为:50*50^3*logd。
矩阵乘法的代码如下:
#include<stdio.h>
#include<algorithm>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<vector>
#include<iostream>
#include<string.h>
#include<string>
#include<math.h>
#include<stdlib.h>
#define inff 0x3fffffff
#define eps 1e-8
#define nn 55
#define mod 1000000007
typedef long long LL;
using namespace std;
int n,m,d;
struct node
{
int en,next;
}E[nn*nn];
int p[nn],num;
void init()
{
memset(p,-1,sizeof(p));
num=0;
}
void add(int st,int en)
{
E[num].en=en;
E[num].next=p[st];
p[st]=num++;
}
struct Matrix
{
int l,r;
double a[55][55];
void clear()
{
l=r=0;
memset(a,0,sizeof(a));
}
Matrix operator*(const Matrix &b) const
{
Matrix tem;
tem.clear();
tem.l=l,tem.r=b.r;
for(int i=1;i<=tem.l;i++)
{
for(int j=1;j<=tem.r;j++)
{
for(int k=1;k<=r;k++)
tem.a[i][j]+=a[i][k]*b.a[k][j];
}
}
return tem;
}
}ma,ix,ans;
Matrix operator^(Matrix b,int y)
{
Matrix tem;
tem.clear();
tem.l=b.l,tem.r=b.r;
for(int i=1;i<=tem.l;i++)
{
for(int j=1;j<=tem.r;j++)
{
if(i==j)
tem.a[i][j]=1;
}
}
while(y)
{
if(y%2)
{
tem=tem*b;
}
y/=2;
b=b*b;
}
return tem;
}
int main()
{
int t,i,u,v,j,k,w;
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&n,&m,&d);
init();
for(i=1;i<=m;i++)
{
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
int bian;
ma.clear();
ma.l=ma.r=n;
for(i=1;i<=n;i++)
{
bian=0;
for(j=p[i];j+1;j=E[j].next)
{
bian++;
}
for(j=p[i];j+1;j=E[j].next)
{
w=E[j].en;
ma.a[i][w]=(1.0)/bian;
}
}
for(i=1;i<=n;i++)
{
ix.clear();
ix.l=ix.r=n;
for(j=1;j<=n;j++)
{
for(k=1;k<=n;k++)
{
if(j==i)
ix.a[j][k]=0;
else
ix.a[j][k]=ma.a[j][k];
}
}
ans.clear();
ans.l=n,ans.r=1;
for(j=1;j<=n;j++)
{
if(i==j)
ans.a[j][1]=0;
else
ans.a[j][1]=(1.0/n);
}
ans=(ix^d)*ans;
double re=0;
for(j=1;j<=n;j++)
re+=ans.a[j][1];
printf("%.8lf\n",re);
}
}
return 0;
}
记忆化搜索代码如下:
#include<stdio.h>
#include<algorithm>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<vector>
#include<iostream>
#include<string.h>
#include<string>
#include<math.h>
#include<stdlib.h>
#define inff 0x3fffffff
#define eps 1e-8
#define nn 55
#define mod 1000000007
typedef long long LL;
using namespace std;
int n,m,d;
struct node
{
int en,next;
}E[nn*nn];
int p[nn],num;
void init()
{
memset(p,-1,sizeof(p));
num=0;
}
void add(int st,int en)
{
E[num].en=en;
E[num].next=p[st];
p[st]=num++;
}
double dp[55][11000];
bool vis[55][11000];
int jin;
double dfs(int id,int step)
{
if(id==jin)
return 0;
if(vis[id][step])
return dp[id][step];
if(step==d)
return 1.0;
vis[id][step]=true;
int i,w;
dp[id][step]=0;
int bian=0;
double ix=0;
for(i=p[id];i+1;i=E[i].next)
{
w=E[i].en;
ix+=dfs(w,step+1);
bian++;
}
dp[id][step]=ix/bian;
return dp[id][step];
}
int main()
{
int t,i,u,v,j,k;
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&n,&m,&d);
init();
for(i=1;i<=m;i++)
{
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
double ans;
for(i=1;i<=n;i++)
{
ans=0;
for(j=1;j<=n;j++)
{
for(k=0;k<=d;k++)
vis[j][k]=false;
}
jin=i;
for(j=1;j<=n;j++)
{
ans+=(1.0/n)*dfs(j,0);
}
printf("%.8lf\n",ans);
}
}
return 0;
}