• B1877 [SDOI2009]晨跑 费用流


    其实之前写过一个板子,但是一点印象都没有,所以今天重写了一下,顺便把这个题当成板子就行了。

    其实费用流就是把bfs换成spfa,但是中间有一个原则,就是费用优先,在费用(就是c)上跑spfa,顺便求出流量。

    其实理解起来还算简单,就是先spfa找最小费用路径,然后在路径上找能跑的最大流。

    题干:

    Description
    Elaxia最近迷恋上了空手道,他为自己设定了一套健身计划,比如俯卧撑、仰卧起坐等 等,不过到目前为止,他
    坚持下来的只有晨跑。 现在给出一张学校附近的地图,这张地图中包含N个十字路口和M条街道,Elaxia只能从 一
    个十字路口跑向另外一个十字路口,街道之间只在十字路口处相交。Elaxia每天从寝室出发 跑到学校,保证寝室
    编号为1,学校编号为N。 Elaxia的晨跑计划是按周期(包含若干天)进行的,由于他不喜欢走重复的路线,所以 
    在一个周期内,每天的晨跑路线都不会相交(在十字路口处),寝室和学校不算十字路 口。Elaxia耐力不太好,
    他希望在一个周期内跑的路程尽量短,但是又希望训练周期包含的天 数尽量长。 除了练空手道,Elaxia其他时间
    都花在了学习和找MM上面,所有他想请你帮忙为他设计 一套满足他要求的晨跑计划。
    Input
    第一行:两个数N,M。表示十字路口数和街道数。 
    接下来M行,每行3个数a,b,c,表示路口a和路口b之间有条长度为c的街道(单向)。
    N ≤ 200,M ≤ 20000。
    Output
    两个数,第一个数为最长周期的天数,第二个数为满足最长天数的条件下最短的路程长 度。
    Sample Input
    7 10
    1 2 1
    1 3 1
    2 4 1
    3 4 1
    4 5 1
    4 6 1
    2 5 5
    3 6 6
    5 7 1
    6 7 1
    Sample Output
    2 11
    HINT
    Source

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<ctime>
    #include<queue>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    #define duke(i,a,n) for(int i = a;i <= n;i++)
    #define lv(i,a,n) for(int i = a;i >= n;i--)
    #define clean(a) memset(a,0,sizeof(a))
    const int INF = 1 << 30;
    typedef long long ll;
    typedef double db;
    template <class T>
    void read(T &x)
    {
        char c;
        bool op = 0;
        while(c = getchar(), c < '0' || c > '9')
            if(c == '-') op = 1;
        x = c - '0';
        while(c = getchar(), c >= '0' && c <= '9')
            x = x * 10 + c - '0';
        if(op) x = -x;
    }
    template <class T>
    void write(T x)
    {
        if(x < 0) putchar('-'), x = -x;
        if(x >= 10) write(x / 10);
        putchar('0' + x % 10);
    }
    const int N = 100005;
    struct node
    {
        int l,r,c,f,nxt,other;
    }a[N * 2];
    int len = 1,lst[N],st,ed;
    void add(int x,int y,int f,int c)
    {
        int k1,k2 = 0;
        a[++len].l = x;
        a[len].r = y;
        a[len].c = c;
        a[len].f = f;
        a[len].nxt = lst[x];
        lst[x] = len;
        k1 = len;
        a[++len].l = y;
        a[len].r = x;
        a[len].c = -c;
        a[len].f = 0;
        a[len].nxt = lst[y];
        lst[y] = len;
        k2 = len;
        a[k1].other = k2;
        a[k2].other = k1;
    }
    int n,m,dis[N],flow[N],vis[N];
    int pre[N],head[N],ans1 = 0,ans2 = 0;
    queue <int> qu;
    bool spfa()
    {
        clean(vis);
        memset(dis,70,sizeof(dis));
        memset(flow,70,sizeof(flow));
        memset(pre,0,sizeof(pre));
        qu.push(st);
        vis[st] = 1;
        dis[st] = 0;
        pre[st] = 0;
        while(!qu.empty())
        {
            int x = qu.front();
            qu.pop();
            for(int k = lst[x];k;k = a[k].nxt)
            {
                if(a[k].f == 0)continue;
                int y = a[k].r;
                if(dis[y] > dis[x] + a[k].c)
                {
                    dis[y] = dis[x] + a[k].c;
                    pre[y] = x;head[y] = k;
                    flow[y] = min(flow[x],a[k].f);
                    if(!vis[y])
                    vis[y] = 1,qu.push(y);
                }
            }
            vis[x] = 0;
        }
        return pre[ed];
    }
    void mvp()
    {
    //    cout<<"QAQ"<<endl;
        int x = flow[ed];
        int i = head[ed];
        ans1 ++;
        /*duke(j,1,2 * n)
        printf("%d ",head[j]);*/
        i = head[ed]; 
        while(i)
        {
    //        cout<<i<<endl;
            ans2 += x * a[i].c;
            a[i].f -= x;
            a[a[i].other].f += x;
            i = head[a[i].l];
    //        cout<<a[i].l<<endl;
        }
    } 
    int main()
    {
        read(n);read(m);
        st = 1;ed = n * 2;
        duke(i,1,m)
        {
            int u,v,w;
            read(u);read(v);read(w);
            add(u + n,v,1,w);
        }
        head[a[0].l] = 0;
        duke(i,2,n - 1)
        add(i,i + n,1,0);
        add(1,st + n,INF,0);
        add(n,ed,INF,0);
        while(spfa()) mvp();
        printf("%d %d
    ",ans1,ans2);
        return 0;
    }
    /*
    7 10
    1 2 1
    1 3 1
    2 4 1
    3 4 1
    4 5 1
    4 6 1
    2 5 5
    3 6 6
    5 7 1
    6 7 1
    */
  • 相关阅读:
    python模块的作用和说明
    Python列表推导式和嵌套的列表推导式
    Python数据结构 将列表作为栈和队列使用
    Python解包参数列表及 Lambda 表达式
    Python函数标注
    Python range() 函数
    python序列和其它类型的比较
    Python教程 深入条件控制
    02爬虫requests请求库
    1
  • 原文地址:https://www.cnblogs.com/DukeLv/p/9696404.html
Copyright © 2020-2023  润新知