[CTSC1999][网络流24题] 星际转移

 

36. [CTSC1999][网络流24题] 星际转移

★★★☆   输入文件:home.in   输出文件:home.out   简单对比
时间限制:1 s   内存限制:128 MB

«问题描述:

 

 

 

 

 

 

 

 

 

«编程任务:

 

 

 

 

 

 

 

 

 

«结果输出:

 

 

输入文件示例 输出文件示例

 

 

 

1 3 1 2 -1

home.out

 

#include<cstdio>
#include<cstring>
#include<algorithm>
#define setfile(name) freopen(#name".in","r",stdin);freopen(#name".out","w",stdout);
using namespace std;
const int N=31,D=51,M=1e6+5;
const int inf=2e9;
struct edge{int v,cap,next;}e[M];int tot=1,head[N*D];
int n,m,k,S,T,ans,dis[N*D],q[N*D],a[N][D],h[N];
void add(int x,int y,int z){
    e[++tot].v=y;e[tot].cap=z;e[tot].next=head[x];head[x]=tot;
    e[++tot].v=x;e[tot].cap=0;e[tot].next=head[y];head[y]=tot;
}
bool bfs(){
    memset(dis,-1,sizeof dis);
    unsigned short h=0,t=1;q[t]=S;dis[S]=0;
    while(h!=t){
        int x=q[++h];
        for(int i=head[x];i;i=e[i].next){
            if(e[i].cap&&dis[e[i].v]==-1){
                dis[e[i].v]=dis[x]+1;
                if(e[i].v==T) return 1;
                q[++t]=e[i].v;
            }
        }
    }
    return 0;
}
int dfs(int x,int f){
    if(x==T) return f;
    int used=0,t;
    for(int i=head[x];i;i=e[i].next){
        if(e[i].cap&&dis[e[i].v]==dis[x]+1){
            t=dfs(e[i].v,min(e[i].cap,f));
            e[i].cap-=t;e[i^1].cap+=t;
            used+=t;f-=t;
            if(!f) return used;
        }
    }
    if(!used) dis[x]=-1;
    return used;
}
inline void dinic(){
//    ans=0;
    while(bfs()) ans+=dfs(S,inf);
}
void init(){
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=m;i++){
        scanf("%d%d",&h[i],&a[i][0]);
        for(int j=1;j<=a[i][0];j++){
            scanf("%d",&a[i][j]);
        }
    }
}
void doit(){
    S=0,T=1;
    add(S,3,inf);
    add(2,T,inf);
    for(int day=1;day<=50;day++){
        add(S,day*(n+2)+3,inf);
        add(day*(n+2)+2,T,inf);
        for(int i=1;i<=m;i++){
            int fd=(day-1)%a[i][0]+1;
            int td=(fd!=a[i][0]?fd+1:1);
            add((day-1)*(n+2)+3+a[i][fd],day*(n+2)+3+a[i][td],h[i]);
        }
        for(int i=2;i<=n+3;i++) add((day-1)*(n+2)+i,day*(n+2)+i,inf);
        dinic();
        if(ans>=k){
            printf("%d",day);
            return ;
        }
    }
    printf("0");
}
int main(){
    setfile(home)
    init();
    doit();
    return 0;
}

 

转载于:https://www.cnblogs.com/shenben/p/6537350.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值