[Luogu P2153] [BZOJ 1877] [SDOI2009] 晨跑

版权声明:欢迎转载蒟蒻博客,但请注明出处:blog.csdn.net/lpa20020220 https://blog.csdn.net/LPA20020220/article/details/82391979

洛谷传送门

BZOJ传送门

题目描述

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

存在 1 n 的边存在。这种情况下,这条边只能走一次。

输入输出格式

输入格式:

第一行:两个数 N , M 。表示十字路口数和街道数。

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

输出格式:

两个数,第一个数为最长周期的天数,第二个数为满足最长天数的条件下最短的路程长 度。

输入输出样例

输入样例#1:

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

输出样例#1:

2 11

说明

对于30%的数据, N 20 M 120

对于100%的数据, N 200 M 20000

解题分析

很明显最小费用最大流嘛…拆点限流, 流量都为 1 , 总之十分套路…

代码如下:

#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <cctype>
#include <cstring>
#include <queue>
#define INF 100000000
#define R register
#define IN inline
#define W while
#define gc getchar()
#define MD 805
#define ME 20050
template <class TT>
IN void in(TT &x)
{
    x = 0; R char c = gc;
    for (; !isdigit(c); c = gc);
    for (;  isdigit(c); c = gc)
    x = (x << 1) + (x << 3) + c - 48;
}
int dot, line, ans, tot, cnt, S, T;
int head[MD], dis[MD], del[MD], pre[MD];
bool vis[MD];
struct Edge {int to, fl, cost, nex;} edge[ME << 4];
IN void add(R int from, R int to, R int fl, R int cost)
{
    edge[++cnt] = {to, fl, cost, head[from]}, head[from] = cnt;
    edge[++cnt] = {from, 0, -cost, head[to]}, head[to] = cnt;
}
namespace MCMF
{
    std::queue <int> q;
    IN bool SPFA()
    {
        q.push(S); R int now;
        std::memset(dis, 63, sizeof(dis));
        dis[S] = 0; del[S] = INF;
        W (!q.empty())
        {
            now = q.front(); q.pop();
            for (R int i = head[now]; ~i; i = edge[i].nex)
            {
                if(edge[i].fl > 0 && dis[edge[i].to] > dis[now] + edge[i].cost)
                {
                    dis[edge[i].to] = dis[now] + edge[i].cost;
                    pre[edge[i].to] = i;
                    del[edge[i].to] = std::min(del[now], edge[i].fl);
                    if(!vis[edge[i].to]) vis[edge[i].to] = true, q.push(edge[i].to);
                }
            }
            vis[now] = false;
        }
        return dis[T] != dis[0];
    }
    IN void updata()
    {
        ans += del[T];
        tot += del[T] * dis[T];
        R int cur = T, pr;
        W (cur != S)
        {
            pr = pre[cur];
            edge[pr].fl -= del[dot];
            edge[pr ^ 1].fl += del[dot];
            cur = edge[pr ^ 1].to;
        }
    }
    void init() {W (SPFA()) updata();}
}
int main(void)
{
    std::memset(head, cnt = -1, sizeof(head));
    int a, b, c;
    in(dot), in(line); S = 1 + dot, T = dot;
    for (R int i = 1; i <= dot; ++i) add(i, i + dot, 1, 0);
    for (R int i = 1; i <= line; ++i)
    {
        in(a), in(b), in(c);
        add(a + dot, b, 1, c);
    }
    MCMF::init();
    printf("%d %d", ans, tot);
}

猜你喜欢

转载自blog.csdn.net/LPA20020220/article/details/82391979