http://poj.org/problem?id=2391

题意:

给定一个无向图,点i处有Ai头牛,点i处的牛棚能容纳Bi头牛,求一个最短时间T,使得在T时间内所有的牛都能进到某一牛棚里去。

思路:

建立一个源点和汇点,源点和牛棚的初始牛量相连,汇点和牛棚容量相连。这样跑最大流,如果最后流量等于牛的总数时,就说明是可以的。

那么,怎么连边呢?
二分时间,根据时间来连边,所以首先我们先跑一遍floyd计算出两点距离。然后在该时间下,如果d【i】【j】,那么就添加边(i,i',INF),表面这段路是可以走的。

注意,这里是需要拆点的!!!

看这个建图,这个没有拆点,那么当我们的时间T=70的时候,只有(2,3)和(3,4)是满足的,但是在图中2-4也相连了,也就是说2-4也可以走,但事实上(2,4)这条路超过了时间设定。所以,不拆点是行不通的。

事实上,这个并不是一个二分图,任意点之间都可能有路径,所以需要拆点。

最后,注意这道题目的数据是很大的!!!

附上数据:http://contest.usaco.org/MAR05_4.htm

 #include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<vector>
#include<stack>
#include<queue>
#include<cmath>
#include<map>
using namespace std;
typedef long long LL;
typedef pair<int,int> pll;
const LL INF=1e16;
const int maxn=+; int n,m;
int full_flow;
int s[maxn],t[maxn];
LL g[maxn][maxn]; struct Edge
{
int from,to,cap,flow;
Edge(int u,int v,int w,int f):from(u),to(v),cap(w),flow(f){}
}; struct Dinic
{
int n,m,s,t;
vector<Edge> edges;
vector<int> G[maxn];
bool vis[maxn];
int cur[maxn];
int d[maxn]; void init(int n)
{
this->n=n;
for(int i=;i<n;++i) G[i].clear();
edges.clear();
} void AddEdge(int from,int to,int cap)
{
edges.push_back( Edge(from,to,cap,) );
edges.push_back( Edge(to,from,,) );
m=edges.size();
G[from].push_back(m-);
G[to].push_back(m-);
} bool BFS()
{
queue<int> Q;
memset(vis,,sizeof(vis));
vis[s]=true;
d[s]=;
Q.push(s);
while(!Q.empty())
{
int x=Q.front(); Q.pop();
for(int i=;i<G[x].size();++i)
{
Edge& e=edges[G[x][i]];
if(!vis[e.to] && e.cap>e.flow)
{
vis[e.to]=true;
d[e.to]=d[x]+;
Q.push(e.to);
}
}
}
return vis[t];
} int DFS(int x,int a)
{
if(x==t || a==) return a;
int flow=, f;
for(int &i=cur[x];i<G[x].size();++i)
{
Edge &e=edges[G[x][i]];
if(d[e.to]==d[x]+ && (f=DFS(e.to,min(a,e.cap-e.flow) ) )>)
{
e.flow +=f;
edges[G[x][i]^].flow -=f;
flow +=f;
a -=f;
if(a==) break;
}
}
return flow;
} int Maxflow(int s,int t)
{
this->s=s; this->t=t;
int flow=;
while(BFS())
{
memset(cur,,sizeof(cur));
flow +=DFS(s,0x3f3f3f3f);
}
return flow;
}
}DC; void floyd()
{
for (int k = ; k <= n; k++)
for (int i = ; i <= n; i++)
for (int j = ; j <= n; j++)
g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
} void init(LL x)
{
DC.init(*n+); for(int i=;i<=n;i++)
{
DC.AddEdge(,i,s[i]);
DC.AddEdge(i+n,*n+,t[i]);
DC.AddEdge(i,i+n,0x3f3f3f3f);
} for(int i=;i<=n;i++)
for(int j=i+;j<=n;j++)
if(g[i][j]<=x)
{
DC.AddEdge(i,j+n,0x3f3f3f3f);
DC.AddEdge(j,i+n,0x3f3f3f3f);
}
} int main()
{
//freopen("D:\\input.txt","r",stdin);
while(scanf("%d%d",&n,&m)!=EOF)
{
full_flow=;
for(int i=;i<=n;i++)
{
scanf("%d%d",&s[i],&t[i]);
full_flow+=s[i];
} for(int i=;i<=n;i++)
{
for(int j=;j<=n;j++)
g[i][j]=INF;
g[i][i]=;
} for(int i=;i<m;i++)
{
int u,v;
LL w;
scanf("%d%d%lld",&u,&v,&w);
if(w<g[u][v]) g[u][v]=g[v][u]=w;
} floyd(); LL L=,R=;
LL ans=-; for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
if(g[i][j]!=INF) R=max(R,g[i][j]); while(L<=R)
{
LL mid=(L+R)/;
init(mid);
if(DC.Maxflow(,*n+)==full_flow)
{
ans=mid;
R=mid-;
}
else L=mid+;
}
printf("%I64d\n",ans);
} return ;
}

最新文章

  1. RFID工作流程
  2. spring与mybatis三种整合方法
  3. Linux教程:SSH免密码登录的方法
  4. 避坑宝典:如何选择HTML5游戏引擎
  5. hdu2888 二维RMQ
  6. 使用地址栏访问CXF Webservice写法
  7. 第三方框架之SDWebImage
  8. 利用PE数据目录的导入表获取函数名及其地址
  9. JVM笔记5:Class文件结构
  10. (转)总结PLSQL的快捷键以及使用技巧
  11. mysql将一个库中表的某几个字段插入到另一个库中的表
  12. angular controller js 压缩后报错解决方案
  13. Linux系统中C&amp;Cpp程序开发(一)
  14. layout_gravity与gravity的区别
  15. HTML5部分元素
  16. 基于NopCommerce的开发框架——缓存、网站设置、系统日志、用户操作日志
  17. ASP.NET Core中的OWASP Top 10 十大风险-失效的访问控制与Session管理
  18. train problem I (栈水题)
  19. Android 进程间的通信
  20. holer实现外网访问内网数据库

热门文章

  1. mysql表大小写问题
  2. php中的魔术方法(Magic methods)和魔术常亮
  3. Visual Studio 2017正式版离线安装方法
  4. 缓存策略 半自动化就是mybaitis只支持数据库查出的数据映射到pojo类上,而实体到数据库的映射需要自己编写sql语句实现,相较于hibernate这种完全自动化的框架我更喜欢mybatis
  5. 运行mlflow命令报错 The &#39;nose&#39; distribution was not found and is required by nose-exclude
  6. Python开发【Django】:Form组件
  7. 最长DNA重复序列长度,并输出该序列。 JAVA
  8. gstreamer应用笔记
  9. Centos7 Zabbix3.2安装
  10. PAT 1111 Online Map[Dijkstra][dfs]