bzoj 3876: [Ahoi2014]支线剧情

Posted lqybzx

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 3876: [Ahoi2014]支线剧情相关的知识,希望对你有一定的参考价值。

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
【JSOI2014 第二轮D2T1】 当初做这题的时候想到是费用流了,可是带上下界的不会写= = 省选后发现有种建图方法比上下界跑得要快很多。 考虑下每个点入度出度关系就可以完成建图了 【鉴于没有这种方法的文字解答我也就不发了。。不过丢个程序供参考(真的想学这种方法的人我相信一定能看懂程序)】 拿了RANK2,比RANK1慢三倍。果然我的程序自带大常数
【后记】 经过不知道多久的努力我终于卡到RANK1了。。下面的代码是184MS的 【后记Ⅱ】 晚上又被刷下去了= =又折腾了一下。。来来去去折腾那么多次也是受够了
#include<queue>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
struct line

     int s,t;
     int c,f;
     int next;
a[100001];
int head[30001];
int edge;
inline void add(int s,int t,int f,int c)

	 a[edge].next=head[s];
     head[s]=edge;
     a[edge].s=s;
     a[edge].t=t;
     a[edge].f=f;
     a[edge].c=c;

int map[301][301];
int pre[10001],dis[30001];
bool v[10001];
int p;
queue <int> Q;
inline bool spfa(int st)

	 memset(v,false,sizeof(v));
     memset(pre,-1,sizeof(pre));
     memset(dis,127/3,sizeof(dis));
     while(!Q.empty())
          Q.pop();
     Q.push(st);
     v[st]=true;
     dis[st]=0;
     int i;
     while(!Q.empty())
     
          int d=Q.front();
          v[d]=false;
          Q.pop();
          for(i=head[d];i!=0;i=a[i].next)
          
               int t=a[i].t;
               if(a[i].f>0&&dis[d]+a[i].c<dis[t])
               
                    dis[t]=dis[d]+a[i].c;
                    pre[t]=i;
                    if(!v[t])
                    
                         Q.push(t);
                         v[t]=true;
                    
               
          
     
     if(pre[p]==-1)
          return false;
     return true;

inline int mfmc(int st)

	 int mincost=0;
     while(spfa(st))
     
          int minf=2100000000;
          int d=p;
          while(d!=st)
          
               minf=min(minf,a[pre[d]].f);
               d=a[pre[d]].s;
          
          d=p;
          while(d!=st)
          
               a[pre[d]].f-=minf;
             //  a[pre[d]^1].f+=minf;
               if(pre[d]%2==1)
			        a[pre[d]+1].f+=minf;
               else
			        a[pre[d]-1].f+=minf;
               d=a[pre[d]].s;
          
          mincost+=minf*dis[p];
     
     return mincost;

int indeg[30001],outdeg[30001];
int s1[30001],s2[30001];
int main()

     int n;
     scanf("%d",&n);
     int i,j,k,s,b,t;
     memset(map,127/3,sizeof(map));
     int sum=0;
     for(i=1;i<=n;i++)
     
          scanf("%d",&s);
          for(j=1;j<=s;j++)
          
               scanf("%d%d",&b,&t);
               sum+=t;
               map[i][b]=t;
            //   map[b][i]=t;
               outdeg[i]++;
               indeg[b]++;
          
     
     indeg[1]=2100000000;
     for(k=1;k<=n;k++)
          for(i=1;i<=n;i++)
               for(j=1;j<=n;j++)
                    if(map[i][k]+map[k][j]<map[i][j])
                         map[i][j]=map[i][k]+map[k][j];
     int p1=0,p2=0;
     p=n+1;
     for(i=1;i<=n;i++)
     
          if(indeg[i]>outdeg[i])
          
               p1++;
               s1[p1]=i;
               edge++;
               add(0,i,indeg[i]-outdeg[i],0);
               edge++;
               add(i,0,0,0);
          
          else if(indeg[i]<outdeg[i])
          
               p2++;
               s2[p2]=i;
               edge++;
               add(i,p,outdeg[i]-indeg[i],0);
               edge++;
               add(p,i,0,0);
          
     
     for(i=1;i<=p1;i++)
     
          for(j=1;j<=p2;j++)
          
               if(map[s1[i]][s2[j]]<20000000)
               
                    edge++;
                    add(s1[i],s2[j],2100000000,map[s1[i]][s2[j]]);
                    edge++;
                    add(s2[j],s1[i],0,-map[s1[i]][s2[j]]);
               
          
     
     sum+=mfmc(0);
     printf("%d\\n",sum);
     return 0;


以上是关于bzoj 3876: [Ahoi2014]支线剧情的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ3876[AHOI2014]支线剧情

网络流BZOJ 3876 [Ahoi2014]支线剧情

bzoj 3876: [Ahoi2014]支线剧情

BZOJ 3876 AHOI2014 支线剧情

bzoj3876: [Ahoi2014]支线剧情 费用流

bzoj3876: [Ahoi2014]支线剧情