• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
AC_Artist.zig_zag
然而我依然在补题、
博客园    首页    新随笔    联系   管理    订阅  订阅

bzoj2879 [Noi2012]美食节

这个题一眼看出是修车,但数据范围有点卡,我傻傻地以为写个zkw就万事大吉了,结果发现zkw还没有spfa跑的快......

这个题的关键是动态加边,就是每次找到已经增广到最新的点的厨师给他加一个新点,这样一共需要增广P次,就可以跑出答案了。

View Code
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#define maxn 100000
#define maxm 100000
#define inf 2147483647
using namespace std;
struct et
{
    int s,t,val,cost,next;
}e[maxm];
int fir[maxn],dis[maxn],pre[maxn],q[maxm],t[200][200],now[maxn],cnt[maxn];
bool inque[maxn];
int n,m,tot,st,ed,sum,fare,k,ans;

bool find()
{
    int head=0,tail=1;
    for (int i=st;i<=ed;i++) dis[i]=inf;
    q[1]=st; dis[st]=0; inque[st]=1;
    while (head<tail)
    {
        int now=q[++head];
        for (int j=fir[now];j;j=e[j].next)
        {
            int k=e[j].t;
            if (e[j].val&&dis[now]+e[j].cost<dis[k])
            {
                dis[k]=dis[now]+e[j].cost;
                pre[k]=j;
                if (!inque[k]) q[++tail]=k,inque[k]=1;
            }
        }
        inque[now]=0;
    }
}

void add(int x,int y,int z,int w)
{
    e[++tot].s=x; e[tot].t=y; e[tot].val=z; e[tot].cost=w; e[tot].next=fir[x]; fir[x]=tot;
    e[++tot].s=y; e[tot].t=x; e[tot].val=0; e[tot].cost=-w; e[tot].next=fir[y]; fir[y]=tot;
}

void adjust()
{
    for (int j=1;j<=m;j++)
        if (e[now[j]].val==0) {
            cnt[j]++;
            now[j]=tot+1;
            add(n+sum*(j-1)+cnt[j],ed,1,0);
            for (int i=1;i<=n;i++) add(i,n+sum*(j-1)+cnt[j],1,t[i][j]*cnt[j]);
            return ;
        }
}

void fare_flow()
{
    find();
    fare+=dis[ed];
    for (int j=pre[ed];j;j=pre[e[j].s]) e[j].val--,e[j^1].val++;
    adjust();
}

int main()
{
    freopen("delicacy.in","r",stdin);
    freopen("delicacy.out","w",stdout);
    scanf("%d%d",&n,&m);
    tot=1;
    int x;
    st=0; 
    for (int i=1;i<=n;i++) {
        scanf("%d",&x);
        add(st,i,x,0);
        sum+=x;
    }
    ed=m*sum+n+1; 
    for (int i=1;i<=n;i++)
        for (int j=1;j<=m;j++)
        {
            scanf("%d",&t[i][j]);
            add(i,n+(j-1)*sum+1,1,t[i][j]);
        }
    for (int i=1;i<=m;i++) 
    {
        cnt[i]=1;
        now[i]=tot+1;
        add(n+(i-1)*sum+1,ed,1,0);
    }
    for (int i=sum;i>0;i--) fare_flow();
    printf("%d\n",fare);
    return 0;
}

 

常数大......

AC without art, no better than WA !
posted @ 2013-04-19 22:04  Zig_zag  阅读(697)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3