列表

详情


NC19901. [AHOI2014]支线剧情

描述

【故事背景】 宅男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可以前往剧情点j,并且观看这段支线剧情需要花费的时间。

输出描述

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

示例1

输入:

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

输出:

24

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(clang++ 11.0.1) 解法, 执行用时: 32ms, 内存消耗: 1848K, 提交时间: 2022-12-26 10:05:54

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10,M=1e6+10;
int n,m,S,T,h[N],e[M],ne[M],f[M],w[M];
int incf[N],pre[N],d[N],st[N],idx,q[N];
void add(int a,int b,int c,int d){
    e[idx]=b,f[idx]=c,w[idx]=d,ne[idx]=h[a],h[a]=idx++;
    e[idx]=a,f[idx]=0,w[idx]=-d,ne[idx]=h[b],h[b]=idx++;
}
bool spfa(){
    memset(d,0x3f,sizeof d);
    memset(incf,0,sizeof incf);
    int hh=0,tt=1;
    q[0]=S,d[S]=0,incf[S]=1e9;
    while(hh!=tt){
        int t=q[hh++];
        if(hh==N)hh=0;
        st[t]=0;
        for(int i=h[t];~i;i=ne[i]){
            int ver=e[i];
            if(f[i]&&d[ver]>d[t]+w[i]){
                d[ver]=d[t]+w[i];
                pre[ver]=i;
                incf[ver]=min(incf[t],f[i]);
                if(!st[ver]){
                    st[ver]=1;
                    q[tt++]=ver;
                    if(tt==N)tt=0;
                    
                }
            }
        }
    }
    return incf[T]>0;
}
void EK(int &flow,int &cost){
    flow=cost=0;
    while(spfa()){
        int t=incf[T];
        flow+=t;
        cost+=t*d[T];
        for(int i=T;i!=S;i=e[pre[i]^1]){
            f[pre[i]]-=t;
            f[pre[i]^1]+=t;
        }
    }
}
int A[N];
signed main(){
    ios::sync_with_stdio(0);cin.tie(0);
    memset(h,-1,sizeof h);
    cin>>n;
    S=0,T=N-1;
    add(T,1,1e9,0);
    int sum=0;
    for(int i=1;i<=n;i++){
        int k;
        cin>>k;
        while(k--){
            int j,w;
            cin>>j>>w;
            add(i,j,1e9,w);
            sum+=w;
            A[i]--,A[j]++;
        }
    }
    for(int i=2;i<=n;i++)add(i,1,1e9,0);
    for(int i=1;i<=n;i++){
        if(A[i]>0)add(S,i,A[i],0);
        if(A[i]<0)add(i,T,-A[i],0);
    }
    
    int flow,cost;
    EK(flow,cost);
//     cout<<flow<<" "<<cost;
    cout<<cost+sum;
}

上一题