POJ2391

来源:互联网 发布:淘宝聚划算怎么买 编辑:程序博客网 时间:2024/06/07 09:26

Problem : Ombrophobic Bovines
Description : 有N个点,每个点都有一些老鼠和一些能容纳老鼠的地方,现在,下午了,老鼠要在规定时间内都找到自己的容纳点,每个点到每个点都有一定的到达时间,现在问你最少要多少时间才能完成这项工作,如果不能完成,输出“-1”。
Solution : Floyd+二分枚举+网络最大流。这题是我的一个学习题。感觉网络流的应用真的是太广了。Floyd不用多说,先求出每个点到每个点的最短路径,然后就是利用每个点老鼠的数量和容纳点的数目来建图。注意!这里要拆点,不然过不了。这个其实也很简单,我们枚举最短时间是为了网络流中的加边。如果小于这个时间就连边,那么如果是这样一种情况:1->2=40, 2->3=70,最短时间是110。那么我们只会加入1->2和2->3这两条边,但是如果不拆点,1->3就会间接连边了。这样不符合我们的要求,那么拆点就可以完美解决这个问题,拆点一般用于任意两点都可以到达的情况。随后就是套最大流的模板了。注意,这里我二分枚举最短时间的时候用了下离散化。这题让我最蛋疼的是交G++WA,C++AC。我都不知道什么鬼。
Code(C++) :

#include <stdio.h>#include <string.h>#include <iostream>#include <queue>#include <set>#define MIN(a,b) ((a)>(b)? (b):(a))using namespace std;typedef long long LL;const int SIZE=200*3+100;const LL INF=(1LL<<60);const int M=200*2+5;int src,des;int d[SIZE];int n;int MAP[SIZE][SIZE];int F,P;int a[M],b[M];LL map[M][M];LL line[M*M];int top;int SUM;void build(LL x){    src=0;    des=2*F+1;    n=2*F;    memset(MAP,0,sizeof(MAP));    for(int i=1;i<=F;i++)        MAP[src][i]=a[i],        MAP[i+F][des]=b[i];    for(int i=1;i<=F;i++)        for(int j=1;j<=F;j++)            if(map[i][j]<=x)                MAP[i][j+F]=SUM;}bool bfs(int src,int des){    memset(d,-1,sizeof(d));    queue<int> que;    que.push(src);    d[src]=0;    while(!que.empty()){        int now=que.front();        que.pop();        for(int i=0;i<=1+n;i++)            if(d[i]==-1&&MAP[now][i]>0){                d[i]=d[now]+1;                que.push(i);            }    }    return d[des]>=0;}int dfs(int t,int sum,int des){    if(t==des)        return sum;    int tmp=sum;    for(int i=0;i<=n+1&&sum;i++)        if(d[i]==d[t]+1&&MAP[t][i]>0){            int a=dfs(i,MIN(sum,MAP[t][i]),des);            MAP[t][i]-=a;            MAP[i][t]+=a;            sum-=a;        }    return tmp-sum;}int DINIC(int src,int des){    int sum=0;    while(bfs(src,des))        sum+=dfs(src,SUM,des);    return sum;}void floyd(){    for(int k=1;k<=F;k++)        for(int i=1;i<=F;i++)            for(int j=1;j<=F;j++)                map[i][j]=MIN(map[i][j],map[i][k]+map[k][j]);}bool judge(LL x){    build(x);    return DINIC(src,des)==SUM;}void work(){    SUM=0;    for(int i=1;i<=F;i++)        scanf("%d%d",&a[i],&b[i]),        SUM+=a[i];    for(int i=1;i<=F;i++){        for(int j=1;j<=F;j++)            map[i][j]=INF;        map[i][i]=0;    }    int x,y;    LL v;    for(int i=1;i<=P;i++)        scanf("%d%d%I64d",&x,&y,&v),        map[x][y]=map[y][x]=MIN(MIN(map[x][y],map[y][x]),v);    floyd();    set<LL> has_set;    for(int i=1;i<=F;i++)        for(int j=i+1;j<=F;j++)            if(map[i][j]<INF)                has_set.insert(map[i][j]);    top=0;    for(set<LL>::iterator it=has_set.begin();it!=has_set.end();++it)        line[top++]=*it;    int l=0,r=top-1,mid;    int ans=-1;    while(l<=r){        mid=(l+r)/2;        if(judge(line[mid]))            ans=mid,            r=mid-1;        else            l=mid+1;    }    if(ans==-1)        puts("-1");    else        printf("%I64d\n",line[ans]);}int main(){    //freopen("in.data","r",stdin);    while(~scanf("%d%d",&F,&P))        work();    return 0;}
0 0
原创粉丝点击