NC17398. [NOI2005]聪聪和可可
描述
在一个魔法森林里,住着一只聪明的小猫聪聪和一只可爱的小老鼠可可。虽 然灰姑娘非常喜欢她们俩,但是,聪聪终究是一只猫,而可可终究是一只老鼠, 同样不变的是,聪聪成天想着要吃掉可可
一天,聪聪意外得到了一台非常有用的机器,据说是叫 GPS,对可可能准确 的定位。有了这台机器,聪聪要吃可可就易如反掌了。于是,聪聪准备马上出发, 去找可可。而可怜的可可还不知道大难即将临头,仍在森林里无忧无虑的玩耍。 小兔子乖乖听到这件事,马上向灰姑娘报告。灰姑娘决定尽快阻止聪聪,拯救可 可,可她不知道还有没有足够的时间。
整个森林可以认为是一个无向图,图中有 N 个美丽的景点,景点从 1 至 N编号。小动物们都只在景点休息、玩耍。在景点之间有一些路连接。
输入描述
数据的第1行为两个整数N 和E,以空格分隔,分别表示森林中的景点数和连接相邻景点的路的条数。
第2行包含两个整数C 和M,以空格分隔,分别表示初始时聪聪和可可所在的景点的编号。
接下来E 行,每行两个整数,第i+2 行的两个整数Ai和Bi表示景点Ai和景点Bi之间有一条路。
所有的路都是无向的,即:如果能从A走到B,就可以从B走到A。
输入保证任何两个景点之间不会有多于一条路直接相连,且聪聪和可可之间必有路直接或间接的相连。
输出描述
输出1个实数,四舍五入保留三位小数,表示平均多少个时间单位后聪聪会把可可吃掉。
示例1
输入:
4 3 1 4 1 2 2 3 3 4
输出:
1.500
说明:
开始时,聪聪和可可分别在景点1和景点4。第一个时刻,聪聪先走,她向更靠近可可(景点4)的景点走动,走到景点2,然后走到景点3;假定忽略走路所花时间。C++14(g++5.4) 解法, 执行用时: 86ms, 内存消耗: 12412K, 提交时间: 2019-01-07 17:05:32
#include<cstdio> #include<cstring> #include<iomanip> #include<iostream> #include<algorithm> #define M 1010 using namespace std; struct abcd{ int to,f,next; }table[M<<1]; int head[M],tot; int n,m,s,t; int degree[M],p[M][M]; double f[M][M]; void Add(int x,int y) { degree[x]++; table[++tot].to=y; table[tot].next=head[x]; head[x]=tot; } void SPFA(int st) { static int f[M],q[65540],v[M],from[M]; static unsigned short r,h; int i; memset(f,0x3f,sizeof f); f[st]=0;q[++r]=st; while(r!=h) { int x=q[++h]; v[x]=0; for(i=head[x];i;i=table[i].next) if(f[table[i].to]>f[x]+1||f[table[i].to]==f[x]+1&&x<from[table[i].to]) { f[table[i].to]=f[x]+1; from[table[i].to]=x; if(!v[table[i].to]) v[table[i].to]=1,q[++r]=table[i].to; } } for(i=1;i<=n;i++) if(i!=st) p[i][st]=from[i]; } double Memorial_Search(int x,int y) { int i; if(x==y) return f[x][y]=0; if(p[x][y]==y) return f[x][y]=1; if(p[p[x][y]][y]==y) return f[x][y]=1; if(f[x][y]>=-1e-7) return f[x][y]; int temp=p[p[x][y]][y]; double re=1; for(i=head[y];i;i=table[i].next) re+=Memorial_Search(temp,table[i].to)/(degree[y]+1); re+=Memorial_Search(temp,y)/(degree[y]+1); return f[x][y]=re; } int main() { int i,x,y; cin>>n>>m>>s>>t; for(i=1;i<=m;i++) scanf("%d%d",&x,&y),Add(x,y),Add(y,x); for(i=1;i<=n;i++) SPFA(i); memset(f,0xc2,sizeof f); cout<<fixed<<setprecision(3)<<Memorial_Search(s,t)<<endl; }
C++11(clang++ 3.9) 解法, 执行用时: 29ms, 内存消耗: 10984K, 提交时间: 2019-03-05 20:42:54
#include<cstdio> #include<cstring> #include<iostream> #include<queue> using namespace std; int n,e,c,m,x,y,fi[1001],ne[2001],w[2001],cnt,dis[1001],p[1001][1001],du[1001]; double f[1001][1001]; bool b[1001]; queue<int> q; void add(int u,int v) { w[++cnt]=v;ne[cnt]=fi[u];fi[u]=cnt; } double cal(int u,int v) { if(u==v) return 0; if(f[u][v]) return f[u][v]; int nex=p[p[u][v]][v]; if(nex==v) return f[u][v]=1; for(int i=fi[v];i;i=ne[i]) f[u][v]+=cal(nex,w[i])/(du[v]+1); f[u][v]+=cal(nex,v)/(du[v]+1);f[u][v]++; return f[u][v]; } int main() { scanf("%d%d%d%d",&n,&e,&c,&m); for(int i=1;i<=e;i++) { scanf("%d%d",&x,&y);add(x,y);add(y,x);f[x][y]=f[y][x]=1;du[x]++;du[y]++; } for(int kkz=1;kkz<=n;kkz++) { memset(dis,127,sizeof(dis)); q.push(kkz);b[kkz]=1;dis[kkz]=0; while(!q.empty()) { int k=q.front();q.pop();b[k]=0; for(int i=fi[k];i;i=ne[i]) { if(dis[w[i]]>dis[k]+1) { dis[w[i]]=dis[k]+1;p[w[i]][kkz]=k; if(!b[w[i]]) { b[w[i]]=1;q.push(w[i]); } } else if(dis[w[i]]==(dis[k]+1) && p[w[i]][kkz]>k) p[w[i]][kkz]=k; } } } printf("%.3lf\n",cal(c,m)); return 0; }