[bzoj3876][AHOI2014]支线剧情 有下界费用流

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

#include<iostream>
#include<cstring>
#include<cstdio>
#define inf 0x7fffffff
using namespace std;
const int N = 305;
int n,ans,cnt=1,T;
int last[N],q[N],d[N];
bool inq[N];
template <class T>
inline bool readIn(T &x)  {
    T flag = 1;  char ch;
    while(!(isdigit(ch = (char) getchar())) && ch != EOF)  if( ch == '-' )  flag = -1;
    if(ch == EOF)  return false;
    for(x = ch - 48; isdigit(ch = (char) getchar()); x = (x << 1) + (x << 3) + ch - 48);
    x *= flag;
    return true;
}
struct Edge{
    int v,to,next,c;
}e[N*N];
void insert( int u, int v, int w, int c ){
    e[++cnt].to = v; e[cnt].next = last[u]; last[u] = cnt; e[cnt].v = w; e[cnt].c = c;
    e[++cnt].to = u; e[cnt].next = last[v]; last[v] = cnt; e[cnt].v = 0; e[cnt].c = -c;
}
bool spfa(){
    int head = 0, tail = 1;
    memset(inq,0,sizeof(inq));
    for( int i = 0; i < T; i++ ) d[i] = inf;
    q[0] = T; d[T] = 0; inq[T] = 1;
    while( head != tail ){
        int now = q[head++]; if( head == T ) head = 0;
        for( int i = last[now]; i; i = e[i].next )
            if( e[i^1].v && d[now]-e[i].c < d[e[i].to] ){
                d[e[i].to] = d[now]-e[i].c;
                if( !inq[e[i].to] ) { inq[e[i].to] = 1; q[tail++] = e[i].to; if( tail == T ) tail = 0; }
            }
        inq[now] = 0;
    }
    return d[0] != inf;
}
int dfs( int x, int f ){
    inq[x] = 1;
    if( x == T ) return f;
    int w, used = 0;
    for( int i = last[x]; i; i = e[i].next )
        if( d[x]-e[i].c == d[e[i].to] && !inq[e[i].to] && e[i].v ){
            w = dfs( e[i].to, min(f-used,e[i].v) );
            e[i].v -= w; e[i^1].v += w; used += w; ans += w*e[i].c;
            if( f == used ) return f;
        }
    return used;
}
void zkw(){
    while(spfa()){
        inq[T] = 1;
        while( inq[T] ){
            memset(inq,0,sizeof(inq));
            dfs(0,inf);
        }
    }
}
int main(){
    readIn(n); T = n+1;
    for( int i = 1; i <= n; i++ ){
        int k; readIn(k);
        insert(i,T,k,0);
        insert(i,1,inf,0);
        for( int j = 1; j <= k; j++ ){
            int uu,ww; readIn(uu); readIn(ww);
            insert(i,uu,inf,ww);
            insert(0,uu,1,ww);
        }
    }
    zkw();
    printf("%d", ans);
    return 0;
}

附poj2396 TLE

#include<iostream>
#include<cstring>
#include<cstdio>
#define INF 0x7fffffff
using namespace std;
const int N = 1005;
bool flag;
int S,T,SS,TT,NN;
int n,m,cnt=1;
int last[N],cur[N],h[N],q[N],d[N];
int l[305][405],r[305][405];
template <class T>
inline bool readIn(T &x)  {
    T flag = 1;  char ch;
    while(!(isdigit(ch = (char) getchar())) && ch != EOF)  if( ch == '-' )  flag = -1;
    if(ch == EOF)  return false;
    for(x = ch - 48; isdigit(ch = (char) getchar()); x = (x << 1) + (x << 3) + ch - 48);
    x *= flag;
    return true;
}
struct Edge{ int to,v,next; } e[N*N];
void insert(int u,int v,int w){
    e[++cnt].to = v; e[cnt].next = last[u]; last[u] = cnt; e[cnt].v = w;
    e[++cnt].to = u; e[cnt].next = last[v]; last[v] = cnt; e[cnt].v = 0;
}
bool bfs(){
     memset(h,-1,sizeof(h));
     int head = 0, tail = 1; q[0] = SS; h[SS] = 0;
     while( head != tail ){
          int now = q[head++];
          for( int i = last[now]; i; i = e[i].next )
              if( e[i].v && h[e[i].to] == -1 ){
                   h[e[i].to] = h[now] + 1;
                   q[tail++] = e[i].to;
              }
     }
     return h[TT] != -1;
}
int dfs( int x, int f ){
     if( x == TT ) return f;
     int w, used = 0;
     for( int i = cur[x]; i; i = e[i].next )
          if( h[e[i].to] == h[x] + 1 ){
               w = dfs(e[i].to, min(e[i].v,f-used));
               e[i].v -= w; e[i^1].v += w; used += w;
               if( e[i].v ) cur[x] = i; if( used == f ) return f;
          }
     if(!used) h[x] = 1;
     return used;
}
void dinic() {while(bfs()){for(int i=0;i<=TT;i++)cur[i]=last[i];dfs(SS,INF);} }
bool right(){
    for( int i = S; i <= T; i++ ){
        if( d[i] > 0 ) insert(SS,i,d[i]); 
        if( d[i] < 0 ) insert(i,TT,-d[i]);
    } dinic();
    for( int i = last[SS]; i; i = e[i].next) if(e[i].v) return false; 
    return true;
}
int main(){
    scanf("%d", &NN);
    int x,y,z; char ch[10];
    while( NN-- ){
        scanf("%d%d", &n, &m);cnt=1;
        memset(last,0,sizeof(last)); cnt = 1; memset(d,0,sizeof(d));
        for( int i = 0; i <= 300; i++ ) for( int j = 0; j <= 300; j++ ) l[i][j] = 0, r[i][j] = 1000;
        flag = 0; S = 0; T = n+m+1; SS = T+1; TT = T+2;
        for( int i = 1,x; i <= n; i++ ) readIn(x), insert(S,i,0), d[S] -= x, d[i] += x;
        for( int i = 1,x; i <= m; i++ ) readIn(x), insert(n+1,T,0), d[n+i] -= x, d[T] += x;
        int Q; scanf("%d", &Q); 
        while(Q--){
            readIn(x); readIn(y); scanf("%s",ch); readIn(z);
            if( !x && !y ) for( int i = 1; i = n; i++ ) for( int j = 1; j <= m; j++ ){
                if( ch[0] == '=' ) l[i][j+n] = r[i][j+n] = z;
                if( ch[0] == '>' ) l[i][j+n] = max(l[i][j+n],z+1);
                if( ch[0] == '<' ) r[i][j+n] = min(r[i][j+n],z-1);
            }if( !x && y ) for( int i = 1; i <= n; i++ ){
                if( ch[0] == '=' ) l[i][y+n] = r[i][y+n] = z;
                if( ch[0] == '>' ) l[i][y+n] = max(l[i][y+n],z+1);
                if( ch[0] == '<' ) r[i][y+n] = min(r[i][y+n],z-1);
            }if( x && !y ) for( int j = 1; j <= m; j++ ){
                if( ch[0] == '=' ) l[x][j+n] = r[x][j] = z;
                if( ch[0] == '>' ) l[x][j+n] = max(l[x][j+n],z+1);
                if( ch[0] == '<' ) r[x][j+n] = min(r[x][j+n],z-1);
            }if( x && y ){
                if( ch[0] == '=' ) l[x][y+n] = r[x][y+n] = z;
                if( ch[0] == '>' ) l[x][y+n] = max(l[x][y+n],z+1);
                if( ch[0] == '<' ) r[x][y+n] = min(r[x][y+n],z-1);
            }
        } for( int i = 1; i <= n; i++ ) for( int j = 1; j <= m; j++ ){
            if( l[i][j+n] > r[i][j+n] ) flag = 1;
            insert(i,j+n,r[i][j+n]-l[i][j+n]);
            d[i] -= l[i][j+n];
            d[j+n] += l[i][j+n];
        }
        if( flag ){ printf("IMPOSSIBLE\n"); continue; }
        insert(T,S,INF);
        if(right()){
            int t = n+m+1;
            for( int i = 1; i <= n; i++ ){
                for( int j = 1; j <= m; j++ ){
                    printf("%d",e[(t<<1)^1].v+l[i][j+n]);
                    if( j != m )printf(" "); t++;
                } printf("\n");
            }
        } else printf("IMPOSSIBLE\n");
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值