【poj2391】【最大流】Ombrophobic Bovines

来源:互联网 发布:ubuntu 不识别分区 编辑:程序博客网 时间:2024/05/21 17:28

这道题可以转换为网络流判定性问题

首先二分出一个最短时间mtime,然后将图中的每个点拆为两个,令a[i]当前牛的数量,b[i]为容纳最大牛的数量,len[a][b]为点a到点b的最短距离,tot为牛的总数

首先floyd求出两点间的最短距离,然后对于每一个点,连边(s,i,a[i]),(i,t,b[i]),(i,i + n,∞)然后len[i][j] < mtime,连一条(i,j + n,∞)边,跑一次最大流。如果maxflow =tot,则说明可以在该时间下可行,这样迭代下去,就求出最短时间了。

代码:

#include<cstdio>#include<cstring>using namespace std;const long long inf = 0x3f3f3f3f3f3f3f3fll;const int maxn = 500;const int maxf = 0x3f3f3f3f;long long len[maxn][maxn];int cur[maxn],dis[maxn],gap[maxn],pre[maxn];int a[maxn],b[maxn];int cap[maxn][maxn];long long ans,limit;int n,m,tot;int s,t;void init(){freopen("poj2391.in","r",stdin);freopen("poj2391.out","w",stdout);}void floyd(){for(int k = 1;k <= n;k++){for(int i = 1;i <= n;i++){for(int j = 1;j <= n;j++){if(i == j || i == k || j == k)continue;if(len[i][k] + len[k][j] < len[i][j])len[i][j] = len[i][k] + len[k][j];}}}}inline int min(int a,int b){return a < b ? a : b; }int sap(){memset(cur,0,sizeof(cur));memset(dis,0,sizeof(dis));memset(gap,0,sizeof(gap));int u = pre[s] = s,maxflow = 0,aug = maxf;int nodenum = 2 * n + 2;gap[0] = nodenum;while(dis[s] < nodenum){loop:   for(int v = cur[u];v < nodenum;v++){if(cap[u][v] && dis[u] == dis[v] + 1){cur[u] = v;aug = min(aug,cap[u][v]);pre[v] = u;u = v;if(v == t){maxflow += aug;for(u = pre[u];v != s;v = u,u = pre[u]){cap[u][v] -= aug;cap[v][u] += aug;}aug = maxf;}goto loop;}}int mind = nodenum;for(int v = 1;v < nodenum;v++){if(cap[u][v] && (mind > dis[v])){cur[u] = v;mind = dis[v];}}if((--gap[dis[u]]) == 0)break;gap[dis[u] = mind + 1]++;u = pre[u];}return maxflow;}void calc(){long long l = 0,r = limit + 1,mid;while(l < r){mid = (l + r) >> 1;memset(cap,0,sizeof(cap));for(int i = 1;i <= n;i++){cap[s][i] = a[i];cap[i][i + n] = (maxf >> 1);cap[i + n][t] = b[i]; }for(int i = 1;i <= n;i++){for(int j = 1;j <= n;j++){if(i != j && len[i][j] <= mid)cap[i][j + n] = (maxf >> 1);}}int tmp = sap();if(tmp == tot)ans = mid,r = mid;else l = mid + 1;}printf("%lld\n",ans);}void readdata(){while(scanf("%d%d",&n,&m) == 2){limit = 0;s = 0,t = 2 * n + 1,tot = 0,ans = -1;for(int i = 1;i <= n;i++){for(int j = 1;j <= n;j++){if(i == j)len[i][j] = 0;else len[i][j] = inf;}}for(int i = 1;i <= n;i++){scanf("%d%d",&a[i],&b[i]);tot += a[i];}for(int j = 1;j <= m;j++){long long u,v,w;scanf("%lld%lld%lld",&u,&v,&w);if(len[u][v] > w){len[u][v] = len[v][u] = w;limit += w;}}floyd();calc();}}int main(){init();readdata();return 0;}


原创粉丝点击