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了~

 

View Code
  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 }

 

 

你可能感兴趣的:(floyd)