poj 2112 Optimal Milking
综合题:floyed+二分答案+网络流判断。
题意:1、K台机器,C头奶牛,M是每台机器处理奶牛的上限。
2、每头奶牛只能走到一台机器。
3、已知(K+C)的矩阵描述了彼此的距离(0表示INF),求在满足M的条件下,每头奶牛所走的最长距离的min。
分析:1、首先,容易想到求出彼此之间的最短路。
2、真正要研究的是矩阵右上角的 K行*C列个点。由M可知,每行最多有M个数字。
3、容易想到以个数建边。即源点s与奶牛连边,容量为1;机器与汇点t连边,容量为M。
4、利用二分,不断逼近所求的最长距离的min,将所有奶牛到机器的路径与min比较,建图并判断最大流是否为C(每头牛都能走到)
View Code
1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 #include<algorithm> 5 #include<iostream> 6 using namespace std; 7 #define N 250 8 #define M 6010 9 #define INF 0x7ffffff 10 11 struct E{ 12 int v,c,next; 13 }e[N*N<<2]; 14 15 int tol,head[N]; 16 int p,k,c,m; 17 int st,ed; 18 int mid; 19 int map[N][N]; 20 21 void Floyd(); 22 void Init(); 23 void Add(int s,int t,int c); 24 int Sap(int s,int t,int n); 25 26 int gap[N]; 27 int dis[N]; 28 int pre[N]; 29 int cur[N]; 30 31 int main() 32 { 33 int i,j; 34 while(scanf("%d%d%d",&k,&c,&m)!=EOF) 35 { 36 p=k+c; 37 for(i=0;i<p;i++) 38 { 39 for(j=0;j<p;j++) 40 { 41 scanf("%d",&map[i][j]); 42 if(i!=j&&!map[i][j]) 43 map[i][j]=INF; 44 } 45 } 46 47 Floyd(); 48 49 int l=0,r=40000; 50 st=p; 51 ed=st+1; 52 int res; //!! 二分写挫了 53 while(l<=r) 54 { 55 mid=(l+r)/2; 56 Init(); 57 if(Sap(st,ed,p+2)){ 58 r=mid-1; 59 res=mid; 60 }else l=mid+1; 61 } 62 printf("%d\n",res); 63 } 64 return 0; 65 } 66 67 void Floyd() 68 { 69 int i,j,pos; 70 for(pos=0;pos<p;pos++) 71 { 72 for(i=0;i<p;i++) 73 { 74 if(map[i][pos]==INF)continue; 75 for(j=0;j<p;j++) 76 { 77 if(map[i][pos]+map[pos][j]<map[i][j]) 78 map[i][j]=map[i][pos]+map[pos][j]; 79 } 80 } 81 } 82 } 83 84 void Init() 85 { 86 int i,j; 87 tol=0; 88 memset(head,-1,sizeof(head)); 89 for(i=0;i<k;i++) 90 { 91 for(j=k;j<p;j++) 92 { 93 if(!i){ 94 Add(st,j,1); 95 } 96 if(mid>=map[i][j]){ 97 Add(j,i,INF); //!! i,j写反了 98 } 99 } 100 Add(i,ed,m); 101 } 102 } 103 104 void Add(int s,int t,int c) 105 { 106 e[tol].v=t; 107 e[tol].c=c; 108 e[tol].next=head[s]; 109 head[s]=tol++; 110 111 e[tol].v=s; 112 e[tol].c=0; 113 e[tol].next=head[t]; 114 head[t]=tol++; 115 } 116 117 int Sap(int s,int t,int n) 118 { 119 int i; 120 for(i=0;i<=n;i++) 121 { 122 dis[i]=gap[i]=0; 123 cur[i]=head[i]; 124 } 125 gap[0]=n; 126 int u=pre[s]=s,maxf=0,aug=INF,v; 127 while(dis[s]<n) 128 { 129 loop: for(i=cur[u];i!=-1;i=e[i].next) 130 { 131 v=e[i].v; 132 if(e[i].c>0&&dis[u]==dis[v]+1){ 133 aug=min(aug,e[i].c); 134 pre[v]=u; 135 cur[u]=i; 136 u=v; 137 if(u==t){ 138 while(u!=s) 139 { 140 u=pre[u]; 141 e[cur[u]].c-=aug; 142 e[cur[u]^1].c+=aug; 143 } 144 maxf+=aug; 145 aug=INF; 146 } 147 goto loop; 148 } 149 } 150 int min=n; 151 for(i=head[u];i!=-1;i=e[i].next) 152 { 153 v=e[i].v; 154 if(e[i].c>0&&dis[v]<min){ 155 min=dis[v]; 156 cur[u]=i; 157 } 158 } 159 if(!(--gap[dis[u]])) 160 break; 161 ++gap[dis[u]=min+1]; 162 u=pre[u]; 163 } 164 return maxf==c; //!! 165 }