20170813(两道题-dijkstra记录路径 BFS)

补题

GYM_100443

C题 Shopping Malls

题意

三维商场,给出点的坐标(200个点),给出点到点的可行路径,1000次询问,要求打出最短路径

解决

能力有限,本来还以为这个题是要用floyd多源最短路径去计算,然后就一直想怎么打印路径的问题…也是之前没有打印最短路径的经验吧…


由于只有200个点,1000次询问,Dijkstra算法复杂度在O(nlogn)(堆优化后)级别,所以直接使用Dijkstra算法打印路径即可

  1. 根据题意手动加边
  2. dijkstra的时候保存前驱
  3. 打印路径
double G[maxn][maxn],dis[maxn];
int pre[maxn];
bool vis[maxn];
int n,m,q;

struct node
{
    double x,y,z;
}N[maxn];

double dist(node n1,node n2)
{
    return sqrt(pow(n1.x-n2.x,2)+pow(n1.y-n2.y,2)+25*pow(n1.z-n2.z,2));
}

void init()
{
    int u,v;
    scanf("%d%d",&n,&m);
    rep(i,0,maxn) rep(j,0,maxn) G[i][j]=INF;            //先把各个结点的距离设为无穷大
    rep(i,0,n) scanf("%lf%lf%lf",&N[i].z,&N[i].x,&N[i].y);
    char s[10];
    rep(i,0,m){
        scanf("%d %d %s",&u,&v,s);
        if(s[0]=='w'||s[0]=='s')
        {
            double d=dist(N[u],N[v]);
            G[u][v]=min(G[u][v],d);                     //自己建立边的时候就选择最小的路径建边
            G[v][u]=min(G[v][u],d);
        }
        if(s[0]=='l')
        {
            G[u][v]=min(G[u][v],1.0);
            G[v][u]=min(G[v][u],1.0);
        }
        if(s[0]=='e')
        {
            double dis1=1.0,dis2=dist(N[u],N[v])*3.0;
            G[u][v]=min(G[u][v],dis1);
            G[v][u]=min(G[v][u],dis2);
        }
    }
}

void dijkstra(int st)
{
    rep(i,0,n) dis[i]=INF,vis[i]=false,pre[i]=-1;       //初始化
    dis[st]=0;
    rep(i,0,n){
        int u,m=INF;
        for(int v=0;vif(!vis[v]&&dis[v]<=m) m=dis[u=v];
        vis[u]=1;
        for(int v=0;vif(dis[v]>dis[u]+G[u][v]){
                dis[v]=dis[u]+G[u][v];
                pre[v]=u;
            }
        }
    }
}

void output(int st,int ed)
{
    if(pre[ed]!=st) output(st,pre[ed]);
    printf("%d ",pre[ed]);
}
int main()
{
    int st,ed;
    init();
    scanf("%d",&q);
    rep(i,0,q){
        scanf("%d%d",&st,&ed);
        if(st==ed){
            printf("%d\n",st);
            continue;
        }
        dijkstra(st);
        output(st,ed);
        printf("%d\n",ed);
    }
}

GYM_100685

G Flood

题意

给一些池塘,每个池塘有最大储水量和当前储水量.给出池塘和池塘的联通关系(注意是单向),往x池子里注入y体积的水,询问z池子最后有多少水

解决

BFS,就是注意一下只有当一个池塘的入度为0的时候才能入队列,相当于跟它联通的池子要把水都流完,它的值才是正确的值

struct node
{
    double now,maxx;
    node(){}
    int indegree;
}N[10005];
vector<int> G[10005];

int main()
{
    int u,v,n,k,x,y,z;
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++)
    {
        scanf("%lf%lf",&N[i].maxx,&N[i].now);
        N[i].indegree=0;
        G[i].clear();
    }
    for(int i=0;i"%d%d",&u,&v);
        G[u].push_back(v);
        //G[v].push_back(u);        ///(ㄒoㄒ)/~~这里纠错纠了半天,没看到是单向边...
        //N[u].indegree++;
        N[v].indegree++;
    }

    scanf("%d%d%d",&x,&y,&z);

    N[x].now+=y;
    queue<int> Q;
    Q.push(x);

    while(!Q.empty())
    {
        int u=Q.front();
        Q.pop();
        if(N[u].now<=N[u].maxx) continue;
        int numv=G[u].size();
        double add=(N[u].now-N[u].maxx)/(double)numv;
        N[u].now=N[u].maxx;

        for(int i=0;iif(N[v].indegree==0) Q.push(v);
        }
    }
    printf("%.6lf\n",N[z].now);
}

你可能感兴趣的:(2017成长点滴)