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
62 2 1 3 2
2 4 3 5 4
2 5 5 6 6
0
0
0
Sample Output
24HINT
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]支线剧情的主要内容,如果未能解决你的问题,请参考以下文章