bzoj1070: [SCOI2007]修车
本来想写美食节的。。但是动态加点不会,今晚有点困,所以就写这题弱化版了。
然后做法就是把一个修理工拆成n个,表示倒数第几个修当前这辆车,这样做的原因就是修一部车的影响是对于后面的车的。
复习一波费用流。
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; int m,n; struct node { int x,y,c,d,next,other; }a[110000];int len,last[1100]; void ins(int x,int y,int c,int d) { int k1,k2; len++;k1=len; a[len].x=x;a[len].y=y;a[len].c=c;a[len].d=d; a[len].next=last[x];last[x]=len; len++;k2=len; a[len].x=y;a[len].y=x;a[len].c=0;a[len].d=-d; a[len].next=last[y];last[y]=len; a[k1].other=k2; a[k2].other=k1; } int st,ed; int w[110][20]; void composition() { for(int i=1;i<=n;i++)ins(st,i,1,0); for(int j=n+1;j<=n+m*n;j++)ins(j,ed,1,0); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) for(int k=1;k<=n;k++) ins(i,j*n+k,1,w[i][j]*(n-k+1)); } //---------composition--------------- int ans; int list[1100],d[1100]; bool v[1100]; int pre[1100],cc[1100]; bool spfa() { memset(d,63,sizeof(d)); memset(v,false,sizeof(v)); list[1]=st;d[st]=0;v[st]=true; memset(cc,0,sizeof(cc));cc[st]=2147483647; int head=1,tail=2; while(head!=tail) { int x=list[head]; for(int k=last[x];k;k=a[k].next) { int y=a[k].y; if(d[y]>d[x]+a[k].d&&a[k].c>0) { d[y]=d[x]+a[k].d; pre[y]=k; cc[y]=min(a[k].c,cc[x]); if(v[y]==false) { v[y]=true; list[tail]=y; tail++;if(tail==1050)tail=1; } } } v[x]=false; head++;if(head==1050)head=1; } if(d[ed]>=999999999)return false; else { ans+=d[ed]*cc[ed]; int y=ed; while(st!=y) { int k=pre[y]; a[k].c-=cc[ed];a[a[k].other].c+=cc[ed]; y=a[k].x; } return true; } } //------------spfa------------------- int main() { scanf("%d%d",&m,&n); st=n+m*n+1,ed=n+m*n+2; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&w[i][j]); composition(); ans=0; while(spfa()==true); printf("%.2lf\n",double(ans)/double(n)); return 0; }
pain and happy in the cruel world.