jzoj5331 【NOIP2017提高A组模拟8.23】壕游戏

19 篇文章 0 订阅
11 篇文章 0 订阅

题面

这里写图片描述
这里写图片描述

分析

这题面tmd太有迷惑性了,比赛的时候完全没有想到费用流。
考虑到k只有200,尝试费用流(思想类似可撤销贪心? )
一次一次增广,每次spfa能跑过去。 每走过一条边,给他的边更新一下贡献。

Demo

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int N=1e3+10,M=8*2e4+10;
int add[M];
int to[M],f[M],cost[M],final[N],tot,nex[M],from[M];
int n,m,k,s;
int S,T;
int pre[N],dis[N],ans;

void _link(int x,int y,int l,int c,int a) {
    to[++tot]=y, nex[tot]=final[x], final[x]=tot;
    add[tot]=a, cost[tot]=c, f[tot]=l;
    from[tot]=x;
} 
void link(int x,int y,int l,int c,int add) 
{_link(x,y,l,c+add,add), _link(y,x,0,-c,add);}

int Q[N*100],head,tail,vis[N];

void spfa() {
    memset(dis,127,sizeof dis);
    head=tail=0;
    dis[S]=0, Q[++tail]=S;
    while (head<tail) {
        int x=Q[++head]; vis[x]=0;
        for (int i=final[x]; i; i=nex[i]) {
            int y=to[i];
            if (f[i] && dis[x]+cost[i]<dis[y]) {
                dis[y]=dis[x]+cost[i];
                pre[y]=i;
                if (!vis[y]) {
                    Q[++tail]=y;
                    vis[y]=1;
                }
            }
        }
    }
}

void go() {
    for (int x=pre[T]; x; x=pre[from[x]]) {
        ans+=cost[x];
        f[x]-=1, f[x^1]+=1;
        cost[x]+=add[x];
        cost[x^1]-=add[x];
    }
}

int main() {
    freopen("game.in","r",stdin);
    // freopen("game.out","w",stdout);
    scanf("%d %d %d %d",&n,&m,&k,&s);
    tot=1, S=n+1, T=S+1;
    link(S,1,k,0,0);
    for (int i=1; i<=s; i++) {
        int u; scanf("%d",&u);
        link(u,T,k,0,0);
    }
    for (int i=1; i<=m; i++) {
        int x,y,a,b,c;
        scanf("%d %d %d %d %d",&x,&y,&a,&b,&c);
        link(x,y,c,b,a);
    }
    int cnt=0;
    while (spfa(), dis[T]!=dis[0]) go(), ++cnt;
    if (cnt<k) printf("-1\n"); else printf("%d",ans);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值