BZOJ1415: [Noi2005]聪聪和可可

题目描述

在一个魔法森林里,住着一只聪明的小猫聪聪和一只可爱的小老鼠可可。虽 然灰姑娘非常喜欢她们俩,但是,聪聪终究是一只猫,而可可终究是一只老鼠, 同样不变的是,聪聪成天想着要吃掉可可。

一天,聪聪意外得到了一台非常有用的机器,据说是叫 GPS,对可可能准确 的定位。有了这台机器,聪聪要吃可可就易如反掌了。于是,聪聪准备马上出发, 去找可可。而可怜的可可还不知道大难即将临头,仍在森林里无忧无虑的玩耍。 小兔子乖乖听到这件事,马上向灰姑娘报告。灰姑娘决定尽快阻止聪聪,拯救可 可,可她不知道还有没有足够的时间。

整个森林可以认为是一个无向图,图中有 NNN 个美丽的景点,景点从 111 至 NNN 编号。小动物们都只在景点休息、玩耍。在景点之间有一些路连接。

当聪聪得到 GPS 时,可可正在景点 MMM(M≤NM≤NMN)处。以后的每个时间单位,可可 都会选择去相邻的景点(可能有多个)中的一个或停留在原景点不动。而去这些地方所发生的概率是相等的。假设有 PPP 个景点与景点 M 相邻,它们分别是景点 R、 景点 S,……景点 Q,在时刻 TTT 可可处在景点 M,则在( T+1 T+1 T+1 )时刻,可可有 1/(1+P)1/(1 +P)1/(1+P) 的可能在景点 R,有 1/(1+P)1/(1 +P)1/(1+P) 的可能在景点 S,……,有 1/(1+P)1/(1 +P)1/(1+P) 的可能在景点 Q,还有1/(1+P)1/(1 +P)1/(1+P)的可能停在景点 M

我们知道,聪聪是很聪明的,所以,当她在景点 C 时,她会选一个更靠近 可可的景点,如果这样的景点有多个,她会选一个标号最小的景点。由于聪聪太 想吃掉可可了,如果走完第一步以后仍然没吃到可可,她还可以在本段时间内再 向可可走近一步。

在每个时间单位,假设聪聪先走,可可后走。在某一时刻,若聪聪和可可位 于同一个景点,则可怜的可可就被吃掉了。

灰姑娘想知道,平均情况下,聪聪几步就可能吃到可可。而你需要帮助灰姑 娘尽快的找到答案。

输入输出格式

输入格式:

数据的第 1 行为两个整数 NNN 和 EEE,以空格分隔,分别表示森林中的景点数和 连接相邻景点的路的条数。

第 2 行包含两个整数 CCC 和 MMM,以空格分隔,分别表示初始时聪聪和可可所在的景点的编号。

接下来 E 行,每行两个整数,第 i+2i+2i+2 行的两个整数 AiA_iAiBiB_iBi表示景点 AiA_iAi和景点 BiB_iBi 之间有一条路。 所有的路都是无向的,即:如果能从 A 走到 B,就可以从 B 走到 A。

输入保证任何两个景点之间不会有多于一条路直接相连,且聪聪和可可之间必有路直接或间接的相连。

输出格式:

输出 1 个实数,四舍五入保留三位小数,表示平均多少个时间单位后聪聪会把可可吃掉。

【输入样例1】
4 3
1 4
1 2
2 3
3 4
【输入样例2】
9 9
9 3
1 2
2 3
3 4
4 5
3 6
4 6
4 7
7 8
8 9

【输出样例1】
1.500
【输出样例2】
2.167

解题思路:

本来算了一下时间,应该是一个遍历的复杂度,大概是可以忍受的,即使再差,最差也是配对的时间复杂度。

然后卡在了建图。

floyd稳定O(n3)想都不用想。

然后我就被卡死了。

回头再看一下数据范围,点数边数很接近诶。

据说Spfa处理稀疏图有奇效。不过Spfa不是死了吗。

这不是05年嘛。

代码:

  1 #include
  2 #include
  3 #include
  4 #include
  5 struct pnt{
  6     int hd;
  7     int no;
  8     double dp[1001];
  9     double num;
 10     int dis[1001];
 11     int nxt[1001];
 12     bool hvn[1001];
 13     bool in;
 14     bool vis[1001];
 15 }p[1001];
 16 struct ent{
 17     int twd;
 18     int lst;
 19 }e[100000];
 20 int n,m;
 21 int cnt;
 22 int cc,kk;
 23 std::queue<int>Q;
 24 void ade(int f,int t)
 25 {
 26     cnt++;
 27     e[cnt].twd=t;
 28     e[cnt].lst=p[f].hd;
 29     p[f].hd=cnt;
 30     return ;
 31 }
 32 void Spfa(int x)
 33 {
 34     for(int i=1;i<=n;i++)
 35     {
 36         p[i].in=0;
 37         p[x].dis[i]=0x3f3f3f3f;
 38         p[x].nxt[i]=0x3f3f3f3f;
 39     }
 40     p[x].dis[x]=0;
 41     p[x].in=1;
 42     Q.push(x);
 43     while(!Q.empty())
 44     {
 45         int s=Q.front();
 46         Q.pop();
 47         p[s].in=false;
 48         for(int i=p[s].hd;i;i=e[i].lst)
 49         {
 50             int to=e[i].twd;
 51             if(p[x].dis[to]>p[x].dis[s]+1)
 52             {
 53                 p[x].dis[to]=p[x].dis[s]+1;
 54                 if(!p[to].in)
 55                     Q.push(to);
 56                 p[to].in=true;
 57             }
 58         }
 59     }
 60     return ;
 61 }
 62 double Dp(int killer,int deserter)
 63 {
 64     if(p[killer].vis[deserter])
 65         return p[killer].dp[deserter];
 66     if(deserter==killer)
 67     {
 68         p[killer].dp[deserter]=0.00;
 69         p[killer].dp[deserter]=true;
 70         return 0.00;
 71     }
 72     int kl=killer;
 73     killer=p[killer].nxt[deserter];
 74     if(killer==deserter)
 75         return 1.00;
 76     killer=p[killer].nxt[deserter];
 77     if(killer==deserter)
 78         return 1.00;
 79     p[kl].dp[deserter]=(1.00/p[deserter].num)*(1.00+Dp(killer,deserter));
 80     for(int i=p[deserter].hd;i;i=e[i].lst)
 81     {
 82         int to=e[i].twd;
 83         p[kl].dp[deserter]+=(1.00/p[deserter].num)*(1.00+Dp(killer,to));
 84     }
 85     
 86     p[kl].vis[deserter]=true;
 87     return p[kl].dp[deserter];
 88 }
 89 int main()
 90 {
 91     scanf("%d%d%d%d",&n,&m,&cc,&kk);
 92     for(int i=1;i<=n;i++)
 93     {
 94         p[i].no=i;
 95         p[i].num=1.00;
 96     }
 97     for(int i=1;i<=m;i++)
 98     {
 99         int a,b;
100         scanf("%d%d",&a,&b);
101         p[a].dp[b]=p[b].dp[a]=1.00;
102         p[a].vis[b]=p[b].vis[a]=true;
103         ade(a,b);
104         ade(b,a);
105         p[a].num+=1.00;
106         p[b].num+=1.00;
107     }
108     for(int i=1;i<=n;i++)
109         Spfa(i);
110     for(int x=1;x<=n;x++)
111         for(int i=p[x].hd;i;i=e[i].lst)
112         {
113             int to=e[i].twd;
114             for(int j=1;j<=n;j++)
115                 if(p[to].dis[j]+1==p[x].dis[j])
116                     p[x].nxt[j]=std::min(to,p[x].nxt[j]);
117         }
118     printf("%.3lf\n",Dp(cc,kk));
119     return 0;
120 }

 

你可能感兴趣的:(BZOJ1415: [Noi2005]聪聪和可可)