输出一行包含一个整数,表示JYY看完所有支线剧情所需要的最少时间。
JYY需要重新开始3次游戏,加上一开始的一次游戏,4次游戏的进程是
对于100%的数据满足N<=300,0<=Ki<=50,1<=Tij<=300,Sigma(Ki)<=5000
解题思路:莫名其妙的A了。
有上下界的最小费用流:相同构图,然后费用流,不过要加上原来必要边的费用。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
const int INF=0x7fffffff;
int n,len,S,SS,TT,T,ans;
int from[100005],next[100005],to[100005],f[100005],wg[100005];
int dis[350],degree[350],q[300000],h[350],pre[350];
bool b[350];
inline int read()
{
char y; int x=0,f=1; y=getchar();
while (y<'0'||y>'9') {if (y=='-') f=-1; y=getchar();}
while (y>='0' && y<='9') {x=x*10+int(y)-48; y=getchar();}
return x*f;
}
void ins(int x,int y,int flow,int w)
{
++len; from[len]=x; to[len]=y; f[len]=flow; wg[len]=w; next[len]=h[x]; h[x]=len;
}
void insert(int x,int y,int flow,int w)
{
ins(x,y,flow,w);
ins(y,x,0,-w);
}
bool spfa()
{
memset(dis,0x7f,sizeof(dis));
memset(b,true,sizeof(b)); b[S]=false;
dis[S]=0; int tail=1,head=0; q[tail]=S;
while (head<tail)
{
++head;
int u=h[q[head]];
while (u!=0)
{
if (f[u]>0 && wg[u]+dis[q[head]]<dis[to[u]])
{
pre[to[u]]=u;
dis[to[u]]=wg[u]+dis[q[head]];
if (b[to[u]])
{
b[to[u]]=false;
++tail; q[tail]=to[u];
}
}
u=next[u];
}
b[q[head]]=true;
}
if (dis[T]<1000000) return true;else return false;
}
void getans()
{
int now=T; int mx=0x7fffffff;
while (now!=S)
{
mx=min(mx,f[pre[now]]);
now=from[pre[now]];
}
now=T;
while (now!=S)
{
ans+=wg[pre[now]]*mx;
f[pre[now]]-=mx; f[pre[now]^1]+=mx;
now=from[pre[now]];
}
}
int main()
{
n=read();
S=n+1; SS=n+2; T=n+3; TT=n+4; len=1; ans=0;
insert(SS,1,INF,0);
for (int i=1;i<=n;++i)
{
insert(i,TT,INF,0);
int x=read();
for (int j=1;j<=x;++j)
{
int y=read(); int w=read(); ans+=w;
--degree[i];
++degree[y];
insert(i,y,INF,w);
}
}
for (int i=1;i<=n;++i)
{
if (degree[i]>0) insert(S,i,degree[i],0);
if (degree[i]<0) insert(i,T,-degree[i],0);
}
insert(TT,SS,INF,0);
while (spfa())
{
getans();
}
printf("%d",ans);
}