zoukankan      html  css  js  c++  java
  • BZOJ 1877: [SDOI2009]晨跑 费用流

    1877: [SDOI2009]晨跑

    Time Limit: 1 Sec  

    Memory Limit: 256 MB

    题目连接

    http://www.lydsy.com/JudgeOnline/problem.php?id=1877

    Description

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

    Input

    第一行:两个数N,M。表示十字路口数和街道数。 接下来M行,每行3个数a,b,c,表示路口a和路口b之间有条长度为c的街道(单向)。

    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

     对于30%的数据,N ≤ 20,M ≤ 120。
    对于100%的数据,N ≤ 200,M ≤ 20000。

    题意

    题解:

    网络流,费用流

    因为得保证每条边只能经过一次,那么我们得拆点

    代码:

    //qscqesze
    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <ctime>
    #include <iostream>
    #include <algorithm>
    #include <set>
    #include <bitset>
    #include <vector>
    #include <sstream>
    #include <queue>
    #include <typeinfo>
    #include <fstream>
    #include <map>
    #include <stack>
    typedef long long ll;
    using namespace std;
    //freopen("D.in","r",stdin);
    //freopen("D.out","w",stdout);
    #define sspeed ios_base::sync_with_stdio(0);cin.tie(0)
    #define maxn 200500
    #define mod 1001
    #define eps 1e-9
    #define pi 3.1415926
    int Num;
    //const int inf=0x7fffffff;
    const ll inf=999999999;
    inline ll read()
    {
        ll x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    //*************************************************************************************
    const int MAXN = 1000;
    const int MAXM = 50000;
    const int INF = 0x3f3f3f3f;
    struct Edge
    {
        int to, next, cap, flow, cost;
        int x, y;
    } edge[MAXM],HH[MAXN],MM[MAXN];
    int head[MAXN],tol;
    int pre[MAXN],dis[MAXN];
    bool vis[MAXN];
    int N, M;
    char map[MAXN][MAXN];
    void init()
    {
        N = MAXN;
        tol = 0;
        memset(head, -1, sizeof(head));
    }
    void addedge(int u, int v, int cap, int cost)//左端点,右端点,容量,花费
    {
        edge[tol]. to = v;
        edge[tol]. cap = cap;
        edge[tol]. cost = cost;
        edge[tol]. flow = 0;
        edge[tol]. next = head[u];
        head[u] = tol++;
        edge[tol]. to = u;
        edge[tol]. cap = 0;
        edge[tol]. cost = -cost;
        edge[tol]. flow = 0;
        edge[tol]. next = head[v];
        head[v] = tol++;
    }
    bool spfa(int s, int t)
    {
        queue<int>q;
        for(int i = 0; i < N; i++)
        {
            dis[i] = INF;
            vis[i] = false;
            pre[i] = -1;
        }
        dis[s] = 0;
        vis[s] = true;
        q.push(s);
        while(!q.empty())
        {
            int u = q.front();
            q.pop();
            vis[u] = false;
            for(int i = head[u]; i != -1; i = edge[i]. next)
            {
                int v = edge[i]. to;
                if(edge[i]. cap > edge[i]. flow &&
                        dis[v] > dis[u] + edge[i]. cost )
                {
                    dis[v] = dis[u] + edge[i]. cost;
                    pre[v] = i;
                    if(!vis[v])
                    {
                        vis[v] = true;
                        q.push(v);
                    }
                }
            }
        }
        if(pre[t] == -1) return false;
        else return true;
    }
    //返回的是最大流, cost存的是最小费用
    int minCostMaxflow(int s, int t, int &cost)
    {
        int flow = 0;
        cost = 0;
        while(spfa(s,t))
        {
            int Min = INF;
            for(int i = pre[t]; i != -1; i = pre[edge[i^1]. to])
            {
                if(Min > edge[i]. cap - edge[i]. flow)
                    Min = edge[i]. cap - edge[i]. flow;
            }
            for(int i = pre[t]; i != -1; i = pre[edge[i^1]. to])
            {
                edge[i]. flow += Min;
                edge[i^1]. flow -= Min;
                cost += edge[i]. cost * Min;
            }
            flow += Min;
        }
        return flow;
    }
    int main()
    {
        init();
        int n=read(),m=read();
        addedge(1,1+n,inf,0);
        addedge(n,n*2,inf,0);
        for(int i=0;i<m;i++)
        {
            int x=read(),y=read(),z=read();
            addedge(x+n,y,1,z);
        }
        for(int i=2;i<n;i++)
            addedge(i,i+n,1,0);
        int ans1 = 0,ans2 = 0;
        ans1 = minCostMaxflow(1,2*n,ans2);
        printf("%d %d
    ",ans1,ans2);
    }
  • 相关阅读:
    词法分析程序
    关于编译原理
    超神c语言文法
    linux基本命令
    用bat来注册ocx
    当web配置文件 appSettings配置的东西越来越多时,可以拆开了。
    MVC的URL路由规则
    ASP.NET MVC 中如何实现基于角色的权限控制
    查cc攻击
    关于session介绍
  • 原文地址:https://www.cnblogs.com/qscqesze/p/4795975.html
Copyright © 2011-2022 走看看