BZOJ 1070 [SCOI2007]修车

费用流。。一开始以为是贪心,后来看见数据范围,就想别的了。。。

这题又是考构图的,省选的构图都好难啊。。。有没有想到。。

 

关键就是把每个技术员拆成n个点,表示这个技术员倒数第几个修的车子。。

考虑第i个工人,他修第j辆车只对后面要修的车有影响,而前面修过的车已经对当前没有影响了。
而这个影响就是后面每个将要修理的车都多等待了time的时间。

太绝了!

 

View Code
 1 #include <iostream>
 2 #include <cstdlib>
 3 #include <cstring>
 4 #include <cstdio>
 5 #include <algorithm>
 6 
 7 #define N 10000
 8 #define M 200000
 9 #define INF 1e9
10 
11 using namespace std;
12 
13 int head[N],next[M],to[M],len[M],pr[M];
14 int n,m,cnt,S,T,mlen;
15 int tim[1000][1000];
16 int dis[N],pre[N],q[M];
17 bool vis[N];
18 
19 inline void add(int u,int v,int r,int w)
20 {
21     to[cnt]=v; len[cnt]=r; pr[cnt]=w; next[cnt]=head[u]; head[u]=cnt++;
22     to[cnt]=u; len[cnt]=0; pr[cnt]=-w; next[cnt]=head[v]; head[v]=cnt++;
23 }
24 
25 inline void read()
26 {
27     memset(head,-1,sizeof head); cnt=0;
28     scanf("%d%d",&m,&n);
29     S=0; T=n+n*m+1;
30     for(int i=1,a;i<=n;i++)
31         for(int j=1;j<=m;j++)
32             scanf("%d",&tim[i][j]);
33     for(int i=1;i<=n;i++) add(S,i,1,0);
34     for(int i=n+n*m;i>=n+1;i--) add(i,T,1,0);
35     for(int i=1;i<=n;i++)
36         for(int j=1;j<=m;j++)
37             for(int k=1;k<=n;k++)
38                 add(i,j*n+k,1,(n-k+1)*tim[i][j]);
39 }
40 
41 inline bool spfa()
42 {
43     memset(pre,-1,sizeof pre);
44     memset(dis,0x3f,sizeof dis);
45     int h=1,t=2,sta;
46     q[1]=S; dis[S]=0; vis[S]=true;
47     while(h<t)
48     {
49         sta=q[h++]; vis[sta]=false;
50         for(int i=head[sta];~i;i=next[i])
51             if(len[i]&&dis[to[i]]>dis[sta]+pr[i])
52             {
53                 dis[to[i]]=dis[sta]+pr[i];
54                 pre[to[i]]=i;
55                 if(!vis[to[i]]) q[t++]=to[i],vis[to[i]]=true;
56             }
57     }
58     return pre[T]!=-1;
59 }
60 
61 inline void updata()
62 {
63     mlen=INF;
64     for(int i=pre[T];~i;i=pre[to[i^1]])
65         mlen=min(mlen,len[i]);
66     for(int i=pre[T];~i;i=pre[to[i^1]])
67         len[i]-=mlen,len[i^1]+=mlen;
68 }
69 
70 inline void go()
71 {
72     int ans=0;
73     while(spfa()) updata(),ans+=dis[T]*mlen;
74     printf("%.2lf\n",double(ans)/n);
75 }
76 
77 int main()
78 {
79     read();
80     go();
81     return 0;
82 }

 

 

posted @ 2013-01-18 22:54  proverbs  阅读(1519)  评论(0编辑  收藏  举报