【Luogu】P2498拯救小云公主(spfa)

  题目链接

  我水爆了- -

  容易发现可以把两个圆之间连边,左上为起点右下为终点,最小生成树直到起点跟终点连起来,输出边权/2就行。

  然后80.

  并不理解为什么这可以转化成spfa求最短路,邻接矩阵暴力跑一下就AC了。

#include<cstdio>
#include<algorithm>
#include<cctype>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<cmath>
#define maxn 3030
using namespace std;
inline long long read(){
    long long num=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-')    f=-1;
        ch=getchar();
    }
    while(isdigit(ch)){
        num=num*10+ch-'0';
        ch=getchar();
    }
    return num*f;
}

struct Node{    double x,y;    };
inline double calc(Node a,Node b){    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));    }
Node q[maxn];

struct Edge{
    int from,to;
    double val;
    bool operator <(const Edge a)const{
        return val<a.val;
    }
}d[maxn*maxn];
int cnt;

double dis[maxn];
bool vis[maxn];

double mp[maxn][maxn];

int main(){
    int e=read(),n=read(),m=read();
    int up=e+1,down=e+2,left=e+3,right=e+4;
    for(int i=1;i<=right;++i)
        for(int j=1;j<=right;++j)    mp[i][j]=0x7ffffffff;
    for(int i=1;i<=e;++i)    q[i]=(Node){read(),read()};
    for(int i=1;i<=e;++i){
        for(register int j=i+1;j<=e;++j)    mp[i][j]=mp[j][i]=calc(q[i],q[j]);
        mp[up][i]=(n-q[i].x)*2;
        mp[i][down]=(q[i].x-1)*2;
        mp[left][i]=(q[i].y-1)*2;
        mp[i][right]=(m-q[i].y)*2;
    }
    queue<int>f;    f.push(up);    f.push(left);
    for(int i=1;i<=right;++i)    dis[i]=0x7ffffffff;
    dis[up]=dis[left]=0;
    while(!f.empty()){
        int from=f.front();f.pop();    vis[from]=0;
        for(int to=1;to<=right;++to){
            if(max(mp[from][to],dis[from])<dis[to]){
                dis[to]=max(mp[from][to],dis[from]);
                if(vis[to])    continue;
                vis[to]=1;    f.push(to);
            }
        }
    }
    printf("%.2lf\n",min(dis[down],dis[right])/2.0);
    return 0;
}

 

posted @ 2018-04-25 09:48  Konoset  阅读(241)  评论(0编辑  收藏  举报