POJ 2391 floyd+二分+最大流
题意:
有N块田,每块田下雨时可以容纳a[i]头牛,每块田现在有b[i]头牛,给出一些田与田之间的无向路径及距离,问下雨时最少多少时间后所有牛都能到避雨的地方。
题解:
明显又是二分答案。floyd求取两点间最短路
PS:要用long long!!!
一开始我想的是三层的图:
①n个点表示n块田 ②和③各n个点(灭个点i和i',拆点限制容量)
S连①中的点容量a[i],表示一开始有a[i]头奶牛在i点
①中的点连②中的i,当且仅当两块田之间的距离小于二分值时
②和③对应点相连,限制流量
③中的点和T连INF的边
这样果断tle了。
后来发现③中的点没有用,直接在②和T之间限流即可,优化后就ac了~
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #include <algorithm> 5 #include <iostream> 6 7 #define N 1000 8 #define M 140000 9 #define INF 1LL<<55 10 11 using namespace std; 12 13 int head[N],to[M],next[M]; 14 __int64 map[N][N],len[M],l,r,mid,sum,num[N],hold[N]; 15 int q[M*10],layer[N]; 16 int n,m,S,T,cnt,tot; 17 18 struct PX 19 { 20 __int64 a,b,c; 21 }px[M]; 22 23 inline bool cmp(const PX &a,const PX &b) 24 { 25 return a.c<b.c; 26 } 27 28 inline void floyd() 29 { 30 for(int k=1;k<=n;k++) 31 for(int i=1;i<=n;i++) 32 for(int j=1;j<=n;j++) 33 map[i][j]=min(map[i][j],map[i][k]+map[k][j]); 34 for(int i=1;i<=n;i++) 35 for(int j=1;j<=n;j++) 36 r=max(r,map[i][j]); 37 } 38 39 inline void add(int u,int v,__int64 w) 40 { 41 to[cnt]=v; len[cnt]=w; next[cnt]=head[u]; head[u]=cnt++; 42 to[cnt]=u; len[cnt]=0; next[cnt]=head[v]; head[v]=cnt++; 43 } 44 45 inline void read() 46 { 47 memset(head,-1,sizeof head); cnt=0; 48 for(int i=1;i<=n;i++) 49 { 50 for(int j=1;j<=n;j++) 51 map[i][j]=INF; 52 map[i][i]=0; 53 } 54 r=0; S=0; T=n+n+1; 55 for(int i=1;i<=n;i++) 56 { 57 scanf("%I64d%I64d",&num[i],&hold[i]); 58 sum+=num[i]; 59 } 60 __int64 c; 61 for(int i=1,a,b;i<=m;i++) 62 { 63 scanf("%d%d%I64d",&a,&b,&c); 64 map[a][b]=map[b][a]=min(c,map[a][b]); 65 } 66 floyd(); 67 tot=0; 68 for(int i=1;i<=n;i++) 69 for(int j=1;j<=n;j++) 70 px[++tot].a=i,px[tot].b=j,px[tot].c=map[i][j]; 71 sort(px+1,px+1+tot,cmp); 72 } 73 74 inline void build() 75 { 76 memset(head,-1,sizeof head); cnt=0; 77 for(int i=1;i<=tot;i++) 78 { 79 if(px[i].c>mid) break; 80 add(px[i].a,px[i].b+n,INF); 81 } 82 for(int i=1;i<=n;i++) 83 { 84 add(i+n,T,hold[i]); 85 add(S,i,num[i]); 86 } 87 } 88 89 inline bool bfs() 90 { 91 memset(layer,-1,sizeof layer); 92 int h=1,t=2,sta; 93 q[1]=S; layer[S]=0; 94 while(h<t) 95 { 96 sta=q[h++]; 97 for(int i=head[sta];~i;i=next[i]) 98 if(len[i]&&layer[to[i]]<0) 99 { 100 layer[to[i]]=layer[sta]+1; 101 q[t++]=to[i]; 102 } 103 } 104 return layer[T]!=-1; 105 } 106 107 inline __int64 find(int u,__int64 cur_flow) 108 { 109 if(u==T) return cur_flow; 110 __int64 res=0,tmp; 111 for(int i=head[u];~i&&res<cur_flow;i=next[i]) 112 if(len[i]&&layer[to[i]]==layer[u]+1) 113 { 114 tmp=find(to[i],min(cur_flow-res,len[i])); 115 len[i]-=tmp; len[i^1]+=tmp; res+=tmp; 116 } 117 if(!res) layer[u]=-1; 118 return res; 119 } 120 121 __int64 dinic() 122 { 123 __int64 ans=0; 124 while(bfs()) ans+=find(S,INF); 125 return ans; 126 } 127 128 inline void go() 129 { 130 l=0; 131 __int64 ans=-1; 132 r+=1000; 133 while(l<=r) 134 { 135 mid=(l+r)>>1; 136 build(); 137 if(dinic()==sum) ans=mid,r=mid-1; 138 else l=mid+1; 139 } 140 if(ans>=INF) puts("-1"); 141 else printf("%I64d\n",ans); 142 } 143 144 int main() 145 { 146 while(scanf("%d%d",&n,&m)!=EOF) read(),go(); 147 return 0; 148 }
没有人能阻止我前进的步伐,除了我自己!