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

来源:互联网 发布:ipadapp下载不了软件 编辑:程序博客网 时间:2024/05/17 20:25

题面

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

分析

这题面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);}
原创粉丝点击