zoukankan      html  css  js  c++  java
  • BZOJ 3876: [Ahoi2014]支线剧情 带下界的费用流

    3876: [Ahoi2014]支线剧情

    题目连接:

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

    Description

    【故事背景】
    宅男JYY非常喜欢玩RPG游戏,比如仙剑,轩辕剑等等。不过JYY喜欢的并不是战斗场景,而是类似电视剧一般的充满恩怨情仇的剧情。这些游戏往往
    都有很多的支线剧情,现在JYY想花费最少的时间看完所有的支线剧情。
    【问题描述】
    JYY现在所玩的RPG游戏中,一共有N个剧情点,由1到N编号,第i个剧情点可以根据JYY的不同的选择,而经过不同的支线剧情,前往Ki种不同的新的剧情点。当然如果为0,则说明i号剧情点是游戏的一个结局了。
    JYY观看一个支线剧情需要一定的时间。JYY一开始处在1号剧情点,也就是游戏的开始。显然任何一个剧情点都是从1号剧情点可达的。此外,随着游戏的进行,剧情是不可逆的。所以游戏保证从任意剧情点出发,都不能再回到这个剧情点。由于JYY过度使用修改器,导致游戏的“存档”和“读档”功能损坏了,
    所以JYY要想回到之前的剧情点,唯一的方法就是退出当前游戏,并开始新的游戏,也就是回到1号剧情点。JYY可以在任何时刻退出游戏并重新开始。不断开始新的游戏重复观看已经看过的剧情是很痛苦,JYY希望花费最少的时间,看完所有不同的支线剧情。

    Input

    输入一行包含一个正整数N。
    接下来N行,第i行为i号剧情点的信息;
    第一个整数为,接下来个整数对,Bij和Tij,表示从剧情点i可以前往剧
    情点,并且观看这段支线剧情需要花费的时间。

    Output

    输出一行包含一个整数,表示JYY看完所有支线剧情所需要的最少时间。

    Sample Input

    6

    2 2 1 3 2

    2 4 3 5 4

    2 5 5 6 6

    0

    0

    0

    Sample Output

    24

    Hint

    题意

    给你一个拓扑图,你每次可以选择走一条从1开始的路线。

    每条边有边权

    问你花费最少,经过所有的边,问你的花费是多少。

    题解

    画一个比较复杂的图,随便推一推就感觉是网络流了。

    然后发现是带下界的网络流,这样一下这道题就挺傻逼的了。

    对于一条边(x,y,z)表示从x到y,费用为z

    那么建图:

    addedge(S,y,1,z)表示至少经过一次

    addedge(x,y,inf,z)随便经过

    addedge(x,1,inf,0)回到1点

    addedge(x,T,inf,0)随时停止。

    然后跑一遍费用流就好了

    代码

    #include<bits/stdc++.h>
    using namespace std;
    
    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(){
        int n;init();
        scanf("%d",&n);
        int S=0,T=n+1;
        for(int i=1;i<=n;i++){
            int c;scanf("%d",&c);
            addedge(i,T,c,0);
            if(i!=1)addedge(i,1,INF,0);
            for(int j=1;j<=c;j++){
                int a,b;
                scanf("%d%d",&a,&b);
                addedge(S,a,1,b);
                addedge(i,a,INF,b);
            }
        }
        int ans1=0,ans2=0;
        ans1=minCostMaxflow(S,T,ans2);
        cout<<ans2<<endl;
    }
  • 相关阅读:
    企业云盘安全性如何 怎样部署
    Sentinel 控制台部署
    nginx代理静态页面添加二级目录
    java socket
    IDEA
    golang代码生成器
    es 单节点问题
    代码模板
    错误摘要 HTTP 错误 403.14
    安装.Net Framework 4.6.2无法安装的2种情况
  • 原文地址:https://www.cnblogs.com/qscqesze/p/5652608.html
Copyright © 2011-2022 走看看