zoukankan      html  css  js  c++  java
  • [BZOJ 1266] 上学路线Route

    Link:

    BZOJ 1266 传送门

    Solution:

    好不容易自己写出来一道水题,练链式前向星的模板调了一小时o(╯□╰)o

    思路非常好想,既然要想让最短路不成立,使最短路部分不连通即可

    又要求最小代价,就是比较明显的最小割模型了

    Tips:

    1、关于如何快速将所有最短路部分重新建图

    既然$n<=500$,直接上$floyd$,只要判断边的两端到1与$n$的最短距离加上边权的和是否为最短路距离即可

    但一旦$n$增大后能如何简便处理呢?我想到的可以建反图从后往前跑一遍,检查每一条边是否属于任意一条最短路

    但对于此题可以简便处理:正向判断$dist[x]+l(x,y)$是否为$dist[y]$即可

    我们没有必要只筛选出最短路的边,只要保证非最短路到不了终点即可,算是用时间换代码长度吧2333

    2、对于链式前向星实现的网络流算法

    (1)$edge$数组的下标一定要从0开始,这样才能使得$edge[i]$与$edge[i^1]$互为反边

    (2)由于上一条原则,$head$数组一定要初始化为-1,而不是-1与0皆可

    以前只用$vector$写还是不太行啊……

    Code:

    #include <bits/stdc++.h>
    
    using namespace std;
    const int MAXN=505,MAXM=MAXN*MAXN,INF=1<<27;
    int n,m,f[MAXN][MAXN];
    struct data{int x,y,t,c;}dat[MAXM];
    
    namespace Max_Flow //最大流
    {
        int head[MAXN],S,T,level[MAXN],iter[MAXN],tot=-1; //数组坐标一定要从0开始 
        struct edge{int nxt,to,cap;}e[MAXM<<2];
        
        void add_edge(int from,int to,int cap)
        {
            e[++tot].nxt=head[from];e[tot].to=to;e[tot].cap=cap;head[from]=tot;
            e[++tot].nxt=head[to];e[tot].to=from;e[tot].cap=0;head[to]=tot;
        }
        
        bool bfs()
        {
            memset(level,-1,sizeof(level));
            queue<int> q;q.push(S);level[S]=0;
            while(!q.empty())
            {
                int u=q.front();q.pop();
                for(int i=head[u];i!=-1;i=e[i].nxt)
                    if(e[i].cap && level[e[i].to]==-1)
                        level[e[i].to]=level[u]+1,q.push(e[i].to);
            }
            return (level[T]!=-1);
        }
        
        int dfs(int v,int f)
        {
            if(v==T) return f;
            int ret=0;
            for(int &i=iter[v];i!=-1;i=e[i].nxt)
            {
                if(level[e[i].to]==level[v]+1 && e[i].cap)
                {
                    int d=dfs(e[i].to,min(f,e[i].cap));
                    e[i].cap-=d;e[i^1].cap+=d;
                    f-=d;ret+=d;if(!f) break;
                }
            }
            return ret;
        }
        
        int Dinic()
        {
            int ret=0;
            while(bfs())
            {
                for(int i=0;i<MAXN;i++) iter[i]=head[i];
                ret+=dfs(S,INF);
            }
            return ret;
        }
    }
    
    int main()
    {
        using namespace Max_Flow;
        scanf("%d%d",&n,&m);
        memset(f,0x3f,sizeof(f));S=1;T=n;
        for(int i=1;i<=n;i++) f[i][i]=0;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d%d",&dat[i].x,&dat[i].y,&dat[i].t,&dat[i].c);
            int x=dat[i].x,y=dat[i].y;
            f[x][y]=f[y][x]=dat[i].t;
        }
        for(int k=1;k<=n;k++) //最短路部分
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                    f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
        printf("%d
    ",f[1][n]);
        
        memset(head,-1,sizeof(head)); //head一定要赋为-1 
        for(int i=1;i<=m;i++)
        {
            int x=dat[i].x,y=dat[i].y;
            if(f[1][x]+dat[i].t+f[y][n]==f[1][n])
                add_edge(x,y,dat[i].c);
            if(f[1][y]+dat[i].t+f[x][n]==f[1][n])
                add_edge(y,x,dat[i].c);
        }
        printf("%d
    ",Dinic());
        return 0;
    }
  • 相关阅读:
    【Android笔记】Android操作HTTP实现与服务器通信
    【Android笔记】Android与服务器通信 http和socket两种形式
    【网络编程笔记】简单的TCP协议 socket编程(C语言版服务器和客户端)
    【Web后端笔记】基于Socket实现的简单Web服务器搭建
    【Web前端笔记】css让背景图片拉伸填充的属性
    【Android笔记】ServerSocket 与 Socket的区别
    【Android笔记】Android与服务器数据库通信的方法
    【Android笔记】Android的三种网络通信方式
    【Web后端笔记】jsp传递中文数据出现乱码的问题
    【Web后端笔记】jsp 的四个作用域 :page、request、session和application的区别
  • 原文地址:https://www.cnblogs.com/newera/p/9231009.html
Copyright © 2011-2022 走看看