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 }
posted @ 2017-06-14 16:36  草根柴鸡  阅读(239)  评论(0编辑  收藏  举报