poj 2391

来源:互联网 发布:淘宝企业店铺好开吗 编辑:程序博客网 时间:2024/05/21 11:12

poj 2399

     这题有点像二分图最优多重匹配,但还是有区别的。构图时要将每块田地a拆点,即一个入点ax,一个出点ay,如果田地a可达田地b,那么,a的入点要连一条容量无限的边到b的出点那里。最后,对超级源点s,连边给每个入点,容量是该处牛的个数,对超级汇点,连边给每个出点,容量是可容纳牛的个数,二分枚举最长时间(要先求一次最短路,用floyd),若该时间下网络的最大流等于牛的总数,则合乎要求。

      开始做的时候很快就想到了拆点,但是入点和出点的连边正好和上述颠倒了,导致一直wa,现在想想确实也是,因为这样的连边没法让牛的个数这个限制容量起作用;还有认识到就是拆点的适用范围不再只是方格取数这一类题,而是出现点间关系不能用“费用流”来建模时,拆点构造关系是不错的选择(纯属个人理解)。

 

      以下是代码:

 

#include<cstdio>#include<cstring>#include<iostream>using namespace std;const int M=1010000;const int N=1010;const  __int64 inf=(__int64)1<<60;const int INF=1<<29;struct node{int u,v;int cap,flow;int next;}edge[M];int head[N],num;int level[N],queue[N];__int64 map[N][N],store[N][2];__int64 sum=0,limit=0;int n,m,s,t,ver;void init1(){int i,j;for(i=1;i<=n;i++)for(j=1;j<=n;j++)if(i==j) map[i][j]=0;else map[i][j]=inf;s=0;t=2*n+1;ver=t+1;sum=0;}void init(){int i;for(i=0;i<=2*n+5;i++){head[i]=-1;}num=0;}void addege(int u,int v,int cap){edge[num].u=u;edge[num].v=v;edge[num].cap=cap;edge[num].next=head[u];head[u]=num++;edge[num].u=v;edge[num].v=u;edge[num].cap=0;edge[num].next=head[v];head[v]=num++;}void floyd(){int i,j,k;for(k=1;k<=n;k++)for(i=1;i<=n;i++)for(j=1;j<=n;j++)if(map[i][k]!=inf && map[k][j]!=inf && map[i][j]>map[i][k]+map[k][j])map[i][j]=map[i][k]+map[k][j];}int sap(){    int NN=t+1;    int pre[N],cur[N],dis[N],gap[N];int flow=0,aug=INF,u;bool flag;int i;for(i=0;i<=NN;i++){cur[i]=head[i];gap[i]=dis[i]=0;}gap[s]=NN;u=pre[s]=s;while(dis[s]<NN){flag=0;for(int &j=cur[u];j!=-1;j=edge[j].next){int v=edge[j].v;if(edge[j].cap>0 && dis[u]==dis[v]+1){flag=1;if(edge[j].cap<aug) aug=edge[j].cap;pre[v]=u;u=v;if(u==t){flow+=aug;while(u!=s){u=pre[u];edge[cur[u]].cap-=aug;edge[cur[u]^1].cap+=aug;}aug=INF;}break;}}if(flag) continue;int mindis=NN;for(int j=head[u];j!=-1;j=edge[j].next){int v=edge[j].v;if(edge[j].cap>0 && dis[v]<mindis){mindis=dis[v];cur[u]=j;}}if((--gap[dis[u]])==0) break;gap[dis[u]=mindis+1]++;u=pre[u];}return flow;}bool check(__int64 mid){int i,j,k;int l;init();for(i=1;i<=n;i++){addege(s,i,store[i][0]);addege(i+n,t,store[i][1]);for(j=1;j<=n;j++){if(map[i][j]<=mid){addege(i,j+n,INF);}}}return sap()==sum;}int main(){ while(scanf("%d%d",&n,&m)==2){int i,j;init1();for(i=1;i<=n;i++){scanf("%d%d",&store[i][0],&store[i][1]);sum+=store[i][0];}for(i=0;i<m;i++){int a,b;__int64 c;scanf("%d%d%I64d",&a,&b,&c);limit+=c;if(c<map[a][b]){limit+=c;map[a][b]=map[b][a]=c;}}floyd();__int64 low=0,high=limit+1;__int64 ans=-1;while(low<=high){__int64 mid=(low+high)/2;if(check(mid)){ans=mid;high=mid-1;}else low=mid+1;}printf("%I64d/n",ans);}return 0;}

原创粉丝点击