HDU 3143 Speedy Escape(最短路+二分+搜索)

来源:互联网 发布:tensorflow cnn 教程 编辑:程序博客网 时间:2024/06/04 23:21

转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents    by---cxlove 

题意:给出一个图,其中有一些点是出口,现在有一个罪犯有一个警察,各在两个不同的点。其中警察有一个最大速度160,问罪犯最少需要多大的速度,保证能从某个出口逃跑。

http://acm.hdu.edu.cn/showproblem.php?pid=3143 

yobobobo给推荐的题,当时和他分析了下,点的个数不多,只有100。

对于答案肯定二分,然后我的想法是,首先预处理出每两个点的最短路径,然后判断可行不可行,结果SB了,最短路径肯定不是一条。

但是再一想,n=100,二分之后还是可以暴力搞的。

由于 各种问题,中途也出现了各种奇葩错误。

我开始求的最短路求的是时间,然后对于每个二分的速度,我都要求一次spfa,果断超时。

然后就假设一个速度,求一次spfa,之后根据比例转换一下。还是各种不能过

其间和yobobobo两份错误代码,对拍,还是发现了错误,然后yobobobo过了,我还在跪。

发现我写的spfa不太好,影响精度,直接spfa两次,从罪犯和警察的起点出现,求出到各个点的最短路径长度。这样就是整数,而且在之后的判断中,可以把除法优化成乘法,确保了精度问题。

当中有一步,是可以通过所有点预处理一下,罪犯的速度上界,yobobobo的做法是首先跑一遍bfs或者spfa判断是否可行。也就 是罪犯一定能逃脱的前提是存在一条路径,不经过警察的起点,能到达终点,因为罪犯的速度可以为正无穷。

但是我还是各种WA,找了yobobobo对拍了数据,各种姿势调整后,终于过了,而且还测了各种其它姿势。

注意的地方:

1、对于无解可以spfa或者bfs判断一下,上面提出的有解的必要条件肯定没问题

2、对于罪犯对整个图的最短路,需要注意的是不能经过警察的起点

3、在二分速度之后,判断可以bfs,或者dfs,便是判断可以走到哪些点,条件就是罪犯到达的时间早于警察到达的时间,如果可以则扩展,注意的是每个点只需要判断一次,不需要像DFS那样恢复现场

4、这题的精度要求是1e-6,可是sample给的精度很高,误导了yobobobo,搞得我们都用了1e-10,其实姿势正确1e-6就能过,原以为样例小数据都能这么大误差,所以把精度控制地很严,导致多次TLE

PS:spfa写错好几个地方 ,SB到极点

#include<iostream>  #include<cstdio>  #include<map>  #include<cstring>  #include<cmath>  #include<vector>  #include<algorithm>  #include<set>  #include<string>  #include<queue>  #define inf 1600005  #define M 40  #define N 200005  #define maxn 300005  #define eps 1e-7#define zero(a) fabs(a)<eps  #define Min(a,b) ((a)<(b)?(a):(b))  #define Max(a,b) ((a)>(b)?(a):(b))  #define pb(a) push_back(a)  #define mp(a,b) make_pair(a,b)  #define mem(a,b) memset(a,b,sizeof(a))  #define LL unsigned long long  #define MOD 2012  #define lson step<<1#define rson step<<1|1#define sqr(a) ((a)*(a))  #define Key_value ch[ch[root][1]][0]  #define test puts("OK");  #define pi acos(-1.0)#pragma comment(linker, "/STACK:1024000000,1024000000")  using namespace std;  struct Edge{    int v,w,next;}e[100005];int start[105],tot;bool ext[105];int p1,p2;int n,m,ee;int a[105][105];int police[105],pep[105];void add(int u,int v,int w){    e[tot].v=v;e[tot].w=w;e[tot].next=start[u];    start[u]=tot++;}bool mark;bool vis[105];double v_p,v_o=160;void dfs(int u,int pre){    if(mark) return;    if(police[u]*v_p<=pep[u]*v_o) return ;    vis[u]=true;    if(ext[u]) {mark=true;return;}    for(int i=start[u];i!=-1;i=e[i].next){        int v=e[i].v;        if(v==pre||vis[v]) continue;        dfs(v,u);        if(mark) return ;    }}bool check(double vv){    mark=false;    v_p=vv;    mem(vis,false);    dfs(p1,0);    return mark;}void slove(){    double low=0,mid,high=0;    for(int i=1;i<=n;i++){        if(!police[i]) continue;        high=max(high,(double)pep[i]*v_o/police[i]);    }    high+=2*eps;    double ans=-1;    while(low+eps<high){        mid=(low+high)/2;        if(check(mid)){            ans=mid;            high=mid;        }        else low=mid;    }    if(ans<0) puts("IMPOSSIBLE");    else printf("%.10f\n",ans);}void Spfa(int s,int *dist){    queue<int>que;    while(!que.empty()) que.pop();    bool flag[105];mem(flag,false);    for(int i=1;i<=n;i++) dist[i]=inf;    dist[s]=0;flag[s]=true;    que.push(s);    while(!que.empty()){        int u=que.front();        flag[u]=false;        que.pop();        for(int i=start[u];i!=-1;i=e[i].next){            int v=e[i].v,w=e[i].w;            if(v==p2) continue;            int tmp=dist[u]+w;            if(tmp<dist[v]){                dist[v]=tmp;                if(!flag[v]){                    que.push(v);                    flag[v]=true;                }            }                    }    }}int main(){    //freopen("in.in","r",stdin);    //freopen("out.out","w",stdout);    while(scanf("%d%d%d",&n,&m,&ee)!=EOF){        for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) a[i][j]=inf;        tot=0;mem(start,-1);        while(m--){            int u,v,w;            scanf("%d%d%d",&u,&v,&w);            add(u,v,w);add(v,u,w);        }          for(int i=1;i<=n;i++)            for(int j=1;j<=n;j++)                if(a[i][j]<inf)                    add(i,j,a[i][j]);        mem(ext,false);        for(int i=0;i<ee;i++){            int k;            scanf("%d",&k);            ext[k]=true;        }        scanf("%d%d",&p1,&p2);        Spfa(p1,pep);        Spfa(p2,police);        slove();    }    return 0;}






原创粉丝点击