您的位置:首页 > 运维架构

poj 2391 Ombrophobic Bovines(最大流+floyd+二分)

2014-08-05 13:44 375 查看
OmbrophobicBovines

TimeLimit:1000MS
MemoryLimit:65536K

TotalSubmissions:14519
Accepted:3170

Description

FJ'scowsreallyhategettingwetsomuchthatthemerethoughtofgettingcaughtintherainmakesthemshakeintheirhooves.Theyhavedecidedtoputarainsirenonthefarmtoletthemknowwhenrainisapproaching.Theyintendtocreatearainevacuationplansothatallthecowscangettoshelterbeforetherainbegins.Weatherforecastingisnotalwayscorrect,though.Inordertominimizefalsealarms,theywanttosoundthesirenaslateaspossiblewhilestillgivingenoughtimeforallthecowstogettosomeshelter.
ThefarmhasF(1<=F<=200)fieldsonwhichthecowsgraze.AsetofP(1<=P<=1500)pathsconnectsthem.Thepathsarewide,sothatanynumberofcowscantraverseapathineitherdirection.
Someofthefarm'sfieldshaverainsheltersunderwhichthecowscanshieldthemselves.Thesesheltersareoflimitedsize,soasinglesheltermightnotbeabletoholdallthecows.Fieldsaresmallcomparedtothepathsandrequirenotimeforcowstotraverse.
Computetheminimumamountoftimebeforerainstartsthatthesirenmustbesoundedsothateverycowcangettosomeshelter.

Input

*Line1:Twospace-separatedintegers:FandP
*Lines2..F+1:Twospace-separatedintegersthatdescribeafield.Thefirstinteger(range:0..1000)isthenumberofcowsinthatfield.Thesecondinteger(range:0..1000)isthenumberofcowstheshelterinthatfieldcanhold.Linei+1describesfieldi.
*LinesF+2..F+P+1:Threespace-separatedintegersthatdescribeapath.Thefirstandsecondintegers(bothrange1..F)tellthefieldsconnectedbythepath.Thethirdinteger(range:1..1,000,000,000)ishowlonganycowtakestotraverseit.

Output

*Line1:Theminimumamountoftimerequiredforallcowstogetunderashelter,presumingtheyplantheirroutesoptimally.Ifitnotpossiblefortheallthecowstogetunderashelter,output"-1".

SampleInput

34
72
04
26
1240
3270
2390
13120

SampleOutput

110


题意:有F块地,告诉你每块地牛的数量和雨篷能遮蔽的牛的数量,有P条路,告诉你每条路连接的两块地和牛走这条路所需要的时间。

要你求让所有的牛都能在雨棚下躲雨的最短时间,如果做不到,输出

-1一下解释来自:http://www.2cto.com/kf/201406/312530.html

二分时间,然后把每个田地之间的最短距离用floyd最短路求出来。然后建立一个源点与汇点,将田地拆分成两个点,在距离之内的

进行连边,要单向连边。然后将源点与田地相连,权值为每个田地的牛的数目,再把另一边的田地与汇点相连,权值为每个田地最大

可避雨的牛的数目。拆开的田地之间权值可以为无穷大。


viewcode#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<queue>
usingnamespacestd;
typedeflonglongll;
constllINF=1LL<<60;
constintinf=1<<30;
constintN=500;
intn,F,P,pre
,cur
;
ints,t,d
;
lldis

;

structom
{
intnum,cap;
}loc
;

structedge
{
intu,v,cap,flow,next;
edge(intu,intv,intcap,intflow,intnext):u(u),v(v),cap(cap),flow(flow),next(next){}
edge(){}
}e[N*N*4];
intecnt;

voidfloyd()
{
for(intk=1;k<=n;k++)
for(inti=1;i<=n;i++)if(dis[i][k]!=INF)
for(intj=1;j<=n;j++)
if(dis[k][j]!=INF&&dis[i][j]>dis[i][k]+dis[k][j])
dis[i][j]=dis[i][k]+dis[k][j];
}

voidaddedge(intu,intv,intw)
{
e[ecnt]=edge(u,v,w,0,pre[u]);
pre[u]=ecnt++;
e[ecnt]=edge(v,u,0,0,pre[v]);
pre[v]=ecnt++;
}

boolvis[N<<1];
boolBFS()
{
memset(vis,0,sizeof(vis));
queue<int>q;
q.push(s);
d[s]=0;
vis[s]=1;
while(!q.empty())
{
intx=q.front();q.pop();
for(inti=pre[x];~i;i=e[i].next)
{
intv=e[i].v;
if(!vis[v]&&e[i].cap>e[i].flow)
{
vis[v]=1;
d[v]=d[x]+1;
q.push(v);
}
}
}
returnvis[t];
}

intDFS(intx,intc)
{
if(x==t||c==0)returnc;
intflow=0,f;
for(int&i=cur[x];~i;i=e[i].next)
{
intv=e[i].v;
if(d[x]+1==d[v]&&(f=DFS(v,min(c,e[i].cap-e[i].flow)))>0)
{
e[i].flow+=f;
e[i^1].flow-=f;
flow+=f;
c-=f;
if(c==0)break;
}
}
returnflow;
}

llMaxflow(ints,intt)
{
intflow=0;
while(BFS())
{
for(inti=s;i<=t;i++)cur[i]=pre[i];
flow+=DFS(s,inf);
}
returnflow;
}

boolis_ok(llm,intsum)
{
s=0,t=n*2+1;
memset(pre,-1,sizeof(pre));
ecnt=0;
for(inti=1;i<=n;i++)
{
addedge(s,i,loc[i].num);
addedge(i+n,t,loc[i].cap);
}

for(inti=1;i<=n;i++)
for(intj=1;j<=n;j++)if(dis[i][j]<=m)
addedge(i,j+n,inf);

returnMaxflow(s,t)>=sum;
}

llsolve()
{
intsumn=0,sumc=0;
for(inti=1;i<=n;i++)
{
scanf("%d%d",&loc[i].num,&loc[i].cap);
sumn+=loc[i].num;
sumc+=loc[i].cap;
}
intu,v,w;
for(inti=1;i<=n;i++)
{
for(intj=1;j<=n;j++)dis[i][j]=INF;
dis[i][i]=0;
}
for(inti=0;i<P;i++)
{
scanf("%d%d%d",&u,&v,&w);
if(w<dis[u][v])dis[u][v]=dis[v][u]=w;
}
if(sumn>sumc)return-1;
floyd();

lll=0,r=0,ans=-1;
for(inti=1;i<n;i++)
{
for(intj=i+1;j<=n;j++)
if(r<dis[i][j]&&dis[i][j]!=INF)r=dis[i][j];
}
while(l<=r)
{
llmid=(l+r)>>1;
if(is_ok(mid,sumn))ans=mid,r=mid-1;
elsel=mid+1;
//printf("ans=%d\n",ans);
}
returnans;
}

intmain()
{
//freopen("in","r",stdin);
while(scanf("%d%d",&n,&P)>0)cout<<solve()<<endl;
return0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: