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 !