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 }

 

 

你可能感兴趣的:(2007)