1. 程式人生 > >bzoj3876 [Ahoi2014&Jsoi2014]支線劇情

bzoj3876 [Ahoi2014&Jsoi2014]支線劇情

-s 一定的 ems 由於 OS ont sizeof style 就是

3876: [Ahoi2014&Jsoi2014]支線劇情

Time Limit: 10 Sec Memory Limit: 256 MB
Submit: 2180 Solved: 1300
[Submit][Status][Discuss]

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

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

Source

Round2 By 佚名上傳

分析:很容易看出這是一個有源匯的有上下界的最小費用最大流問題.

   先建出原圖:源點S向一號點連邊,容量為inf,費用為0. 每個點向它能到達的點連邊,容量為[1,inf],費用為題目給定的費用. 每個點向匯點T連邊,容量為inf,費用為0.

   建出原圖後就好辦了,直接套用模板即可.

#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace
std; const int maxn = 100010,inf = 0x7fffffff; int n,S,T,SS,TT,du[maxn],pos[310][310],ans,head[maxn],to[maxn],nextt[maxn],w[maxn],cost[maxn],tot = 2; int d[maxn],vis[maxn],vis2[maxn]; void add(int x,int y,int z,int p) { cost[tot] = p; w[tot] = z; to[tot] = y; nextt[tot] = head[x]; head[x] = tot++; cost[tot] = -p; w[tot] = 0; to[tot] = x; nextt[tot] = head[y]; head[y] = tot++; } bool spfa() { for (int i = 1; i <= TT; i++) d[i] = inf; memset(vis,0,sizeof(vis)); memset(vis2,0,sizeof(vis2)); d[SS] = 0; vis[SS] = 0; queue <int> q; q.push(SS); while (!q.empty()) { int u = q.front(); q.pop(); vis[u] = 0; for (int i = head[u];i;i = nextt[i]) { int v = to[i]; if (w[i] && d[v] > d[u] + cost[i]) { d[v] = d[u] + cost[i]; if (!vis[v]) { vis[v] = 1; q.push(v); } } } } return d[TT] < inf; } int dfs(int u,int f) { if (u == TT) { ans += d[u] * f; return f; } int res = 0; vis2[u] = 1; for (int i = head[u];i;i = nextt[i]) { int v = to[i]; if (w[i] && !vis2[v] && d[v] == d[u] + cost[i]) { int temp = dfs(v,min(f - res,w[i])); w[i] -= temp; w[i ^ 1] += temp; res += temp; if (res == f) return res; } } return res; } void dinic() { while (spfa()) dfs(SS,inf); } int main() { scanf("%d",&n); S = n + 1; T = S + 1; SS = T + 1; TT = SS + 1; for (int i = 1; i <= n; i++) { int num; scanf("%d",&num); for (int j = 1; j <= num; j++) { int x,y; scanf("%d%d",&x,&y); ans += y; add(i,x,inf,y); pos[i][x] = tot - 1; du[i]--; du[x]++; } add(i,T,inf,0); } add(S,1,inf,0); add(T,S,inf,0); for (int i = 1; i <= T; i++) { if (du[i] > 0) add(SS,i,du[i],0); if (du[i] < 0) add(i,TT,-du[i],0); } dinic(); printf("%d\n",ans); return 0; }

bzoj3876 [Ahoi2014&Jsoi2014]支線劇情