bzoj1070: [SCOI2007]修车(费用流)
1070: [SCOI2007]修车
题目:传送门
题解:
一道挺简单的费用流吧...胡乱建模走起
贴个代码...
1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cmath> 5 #include<algorithm> 6 using namespace std; 7 int n,m,st,ed,ans; 8 struct node 9 { 10 int x,y,c,d,next,other; 11 }a[210000];int len,last[1100]; 12 void ins(int x,int y,int c,int d) 13 { 14 int k1,k2; 15 k1=++len; 16 a[len].x=x;a[len].y=y;a[len].c=c;a[len].d=d; 17 a[len].next=last[x];last[x]=len; 18 19 k2=++len; 20 a[len].x=y;a[len].y=x;a[len].c=0;a[len].d=-d; 21 a[len].next=last[y];last[y]=len; 22 23 a[k1].other=k2; 24 a[k2].other=k1; 25 } 26 int head,tail,list[110000],dis[110000],pre[110000],cc[110000]; 27 bool v[110000]; 28 bool spfa() 29 { 30 memset(cc,0,sizeof(cc));cc[st]=99999999; 31 memset(v,false,sizeof(v));v[st]=true; 32 memset(dis,0x3F,sizeof(dis));dis[st]=0; 33 head=1;tail=2;list[1]=st;pre[st]=0; 34 while(head!=tail) 35 { 36 int x=list[head]; 37 for(int k=last[x];k;k=a[k].next) 38 { 39 int y=a[k].y; 40 if( (a[k].c>0) && (dis[y]>dis[x]+a[k].d) ) 41 { 42 cc[y]= min(cc[x],a[k].c); 43 dis[y]=dis[x]+a[k].d; 44 pre[y]=k; 45 if(!v[y]) 46 { 47 v[y]=true; 48 list[tail++]=y; 49 if(tail==ed+1) tail=1; 50 } 51 52 } 53 } 54 v[x]=false; 55 head++; if(head==ed+1)head=1; 56 } 57 if(dis[ed]>999999999)return false; 58 ans+=dis[ed]*cc[ed]; 59 int x=ed; 60 while(x!=st) 61 { 62 int k=pre[x]; 63 a[k].c-=cc[ed];a[a[k].other].c+=cc[ed]; 64 x=a[k].x; 65 } 66 return true; 67 } 68 int map[1100][1100]; 69 int main() 70 { 71 scanf("%d%d",&m,&n); 72 len=0;memset(last,0,sizeof(last)); 73 for(int i=1;i<=n;i++) 74 for(int j=1;j<=m;j++) 75 { 76 scanf("%d",&map[i][j]); 77 } 78 st=n+m*n+1;ed=st+1; 79 for(int i=1;i<=n;i++) 80 { 81 for(int j=1;j<=m;j++) 82 { 83 for(int k=1;k<=n;k++) 84 { 85 ins(i,j*n+k,1,map[i][j]*(n-k+1)); 86 } 87 } 88 } 89 for(int i=1;i<=n;i++)ins(st,i,1,0); 90 for(int i=n+1;i<=n+n*m;i++)ins(i,ed,1,0); 91 ans=0; 92 while(spfa()); 93 printf("%.2lf\n",double(ans)/n); 94 return 0; 95 }