zoukankan      html  css  js  c++  java
  • BZOJ 3876 支线剧情

    支线剧情

    【故事背景】

    宅男JYY非常喜欢玩RPG游戏,比如仙剑,轩辕剑等等。不过JYY喜欢的并不是战斗场景,而是类似电视剧一般的充满恩怨情仇的剧情。这些游戏往往都有很多的支线剧情,现在JYY想花费最少的时间看完所有的支线剧情。

    【问题描述】

    JYY现在所玩的RPG游戏中,一共有N个剧情点,由1到N编号,第i个剧情点可以根据JYY的不同的选择,而经过不同的支线剧情,前往Ki种不同的新的剧情点。当然如果为0,则说明i号剧情点是游戏的一个结局了。

    JYY观看一个支线剧情需要一定的时间。JYY一开始处在1号剧情点,也就是游戏的开始。显然任何一个剧情点都是从1号剧情点可达的。此外,随着游戏的进行,剧情是不可逆的。所以游戏保证从任意剧情点出发,都不能再回到这个剧情点。由于JYY过度使用修改器,导致游戏的“存档”和“读档”功能损坏了,

    所以JYY要想回到之前的剧情点,唯一的方法就是退出当前游戏,并开始新的游戏,也就是回到1号剧情点。JYY可以在任何时刻退出游戏并重新开始。不断开始新的游戏重复观看已经看过的剧情是很痛苦,JYY希望花费最少的时间,看完所有不同的支线剧情。

    【输入格式】

    输入一行包含一个正整数N。

    接下来N行,第i行为i号剧情点的信息;

    第一个整数为,接下来个整数对,Bij和Tij,表示从剧情点i可以前往剧

    情点,并且观看这段支线剧情需要花费的时间。

    【输出格式】

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

    【样例输入】

    6
    2 2 1 3 2
    2 4 3 5 4
    2 5 5 6 6
    0
    0
    0

    【样例输出】

    24

    【样例解释】

    JYY需要重新开始3次游戏,加上一开始的一次游戏,4次游戏的进程是

    1->2->4,1->2->5,1->3->5和1->3->6。

    对于100%的数据满足N<=300,0<=Ki<=50,1<=Tij<=300,Sigma(Ki)<=5000


    题解:

    题意就是要求走完所有边所需的最小时间(费用)

    相当于有上下界无源汇可行最小费用流

    那么就把题目中给定的边下界设为 1

    重新开始就从每一个点连向点 1 就好了

    具体见图可看代码

    对于超级源与超级汇的连边也一起连在里面了

      1 #include<cmath>
      2 #include<cstdio>
      3 #include<cstdlib>
      4 #include<cstring>
      5 #include<iostream>
      6 #include<algorithm>
      7 using namespace std;
      8 const int maxn = 1e3 + 1;
      9 const int maxm = 3e4 + 1;
     10 const int inf = 1e9 + 7;
     11 int n;
     12 int s, t, nors, nort, sups, supt;
     13 int du[maxn];
     14 int len;
     15 int nex[maxm], fir[maxn], ver[maxm], con[maxm], val[maxm];
     16 bool vis[maxn];
     17 int que[maxm << 1], dis[maxn];
     18 int ans;
     19 inline void Scan(int &x)
     20 {
     21     char c;
     22     bool o = false;
     23     while(!isdigit(c = getchar())) o = (c != '-') ? o : true;
     24     x = c - '0';
     25     while(isdigit(c = getchar())) x = x * 10 + c - '0';
     26     if(o) x = -x;
     27 }
     28 inline void Add(int x, int y, int c, int w)
     29 {
     30     nex[++len] = fir[x];
     31     fir[x] = len;
     32     ver[len] = y;
     33     con[len] = c;
     34     val[len] = w;
     35 }
     36 inline void Ins(int x, int y, int c, int w)
     37 {
     38     Add(x, y, c, w);
     39     Add(y, x, 0, -w);
     40 }
     41 inline void Sup(int x, int y, int l, int r, int w)
     42 {
     43     if(l) du[x] -= l, du[y] += l;
     44     if(l != r) Ins(x, y, r - l, w);
     45 }
     46 inline bool Spfa()
     47 {
     48     int head = 0, tail = 1;
     49     for(int i = 1; i <= supt; ++i)
     50         dis[i] = inf, vis[i] = false;
     51     que[tail] = s;
     52     dis[s] = 0;
     53     vis[s] = true;
     54     while(head < tail)
     55     {
     56         int u = que[++head];
     57         for(int i = fir[u]; i; i = nex[i])
     58         {
     59             if(!con[i]) continue;
     60             int v = ver[i];
     61             if(dis[v] > dis[u] + val[i])
     62             {
     63                 dis[v] = dis[u] + val[i];
     64                 if(!vis[v])
     65                 {
     66                     vis[v] = true;
     67                     que[++tail] = v;
     68                 }
     69             }
     70         }
     71         vis[u] = false;
     72     }
     73     return dis[t] < inf;
     74 }
     75 int Dinic(int u, int f)
     76 {
     77     vis[u] = true;
     78     if(u == t) return f;
     79     int g = f;
     80     for(int i = fir[u]; i; i = nex[i])
     81     {
     82         if(!con[i]) continue;
     83         int v = ver[i];
     84         if(vis[v] || dis[v] != dis[u] + val[i]) continue;
     85         int h = Dinic(v, min(con[i], g));
     86         if(h)
     87         {
     88             con[i] -= h;
     89             con[i ^ 1] += h;
     90             g -= h;
     91             ans += h * val[i];
     92             if(!g) return f;
     93         }
     94     }
     95     return f - g;
     96 }
     97 inline int Flow(int x, int y)
     98 {
     99     s = x, t = y, ans = 0;
    100     while(Spfa()) Dinic(s, inf);
    101     return ans;
    102 }
    103 inline void Init()
    104 {
    105     len = 1;
    106     nors = n << 1 | 1;
    107     nort = nors + 1;
    108     sups = nort + 1;
    109     supt = sups + 1;
    110 }
    111 int main()
    112 {
    113     Scan(n);
    114     int m, x, t;
    115     Init();
    116     for(int i = 1; i <= n; ++i)
    117     {
    118         Scan(m);
    119         Ins(i, supt, m, 0);
    120         while(m--)
    121         {
    122             Scan(x), Scan(t);
    123             Sup(i, x, 1, inf, t);
    124             Ins(sups, x, 1, t);
    125         }
    126         if(i != 1) Ins(i, 1, inf, 0);
    127     }
    128     printf("%d", Flow(sups, supt));
    129 }
  • 相关阅读:
    【C#进阶系列】06 类型和成员基础
    纪中5日T1 1564. 旅游
    纪中17日T1 2321. 方程
    纪中17日T2 2322. capacitor
    纪中10日T1 2313. 动态仙人掌
    纪中14日听课小结 图论 最短路 二分图 差分约束
    一个抓猫的游戏 消遣GAME 持续更新中!
    洛谷P1464 Function  HDU P1579 Function Run Fun
    洛谷P1976 鸡蛋饼
    纪中12日T1 2307. 选择
  • 原文地址:https://www.cnblogs.com/lytccc/p/7009007.html
Copyright © 2011-2022 走看看