Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 14019 | Accepted: 3068 |
Description
Input
Output
Sample Input
3 4 7 2 0 4 2 6 1 2 40 3 2 70 2 3 90 1 3 120
Sample Output
110
Hint
Source
题目大意:
有n头奶牛及牛棚,以及m条边,接下来告诉你n行,每行表示这个牛棚奶牛实际数目,以及能容纳的数目,接下来m行告诉你奶牛从一个牛棚到另一个牛棚所需要的时间,问你,是否所有奶牛能够到达牛棚,如果不能,输出-1,如果能,输出最短时间。
解题思路:
这种最短时间,想到了二分,是否能到达,想到了最短路径,是否能全部容纳,想到了构建一张网络图,来解决。
这题采用了三种网络流解法,sap效率最高,用了300多毫秒,dinic用了700多毫秒,而预留推进,我最喜欢用的,则超时了。
代码一:sap效率最高,用了300多毫秒
#include <iostream> #include <cstdio> #include <cstring> #include <queue> using namespace std; #define INF 2000000000 #define N 100010 typedef long long ll; const int maxn=1100; struct edge{ int u,v,next,cap; }e[maxn*maxn]; int n,head[N],tol,top,st[N]; int src,des,dep[N],gap[N]; void adde(int u,int v,int c){ e[tol].u=u,e[tol].v=v,e[tol].next=head[u],e[tol].cap=c,head[u]=tol++; e[tol].u=v,e[tol].v=u,e[tol].next=head[v],e[tol].cap=0,head[v]=tol++; } void bfs(){//对于反边计算层次 for(int i=0;i<N;i++) dep[i]=N-1; memset(gap,0,sizeof gap); gap[0]=1,dep[des]=0; int q[N],l=0,r=0,u,v; q[r++]=des; while(l!=r){ u=q[l++]; l=l%N; for(int i=head[u];i!=-1;i=e[i].next){ v=e[i].v; if(e[i].cap!=0||dep[v]!=N-1) continue; q[r++]=v; r=r%N; ++gap[dep[v]=dep[u]+1]; } } } int sap(){ bfs(); int u=src,s[N],top=0,res=0,ii; int cur[N]; memcpy(cur,head,sizeof head); while(dep[src]<n){ if(u==des){//求得一条增广路 int minf=INF,pos=n; for(int i=0;i<top;i++){ if(minf>e[s[i]].cap){ minf=e[s[i]].cap; pos=i; } } for(int i=0;i<top;i++){ e[s[i]].cap-=minf; e[s[i]^1].cap+=minf; } top=pos; res+=minf; u=e[s[top]].u;//优化1 } if(dep[u]!=0&&gap[dep[u]-1]==0) break;//出现断层 ii=-1; for(int i=cur[u];i!=-1;i=e[i].next){ if(dep[e[i].v]==N-1) continue; if(e[i].cap!=0&&dep[u]==dep[e[i].v]+1){ii=i;break;} } if(ii!=-1){//有允许弧 cur[u]=ii; s[top++]=ii; u=e[ii].v; }else{//不断回退找增光路 int mind=n; for(int i=head[u];i!=-1;i=e[i].next){ if(e[i].cap==0) continue; if(dep[e[i].v]<mind) mind=dep[e[i].v],cur[u]=i; } --gap[dep[u]]; ++gap[dep[u]=mind+1];//优化2 if(u!=src) u=e[s[--top]].u; } } return res; } const ll inf=1e18; int nn,m,now[maxn],need[maxn],sum; ll dis[maxn][maxn],maxr; void initial(){ sum=0; for(int i=0;i<=nn;i++){ for(int j=0;j<=nn;j++){ dis[i][j]=inf; } dis[i][i]=0; } } void input(){ for(int i=1;i<=nn;i++){ scanf("%d%d",&now[i],&need[i]); sum+=now[i]; } for(int i=0;i<m;i++){ int u,v,x; scanf("%d%d%d",&u,&v,&x); maxr+=x; if(x<dis[u][v]){ dis[u][v]=dis[v][u]=x; } } for(int k=1;k<=nn;k++){ for(int i=1;i<=nn;i++){ for(int j=1;j<=nn;j++){ if(dis[i][k]+dis[k][j]<dis[i][j]) dis[i][j]=dis[i][k]+dis[k][j]; } } } maxr=0; for(int i=1;i<=nn;i++){ for(int j=1;j<=nn;j++){ if(dis[i][j]!=inf && dis[i][j]>maxr) maxr=dis[i][j]; } } } void build(ll c){ tol=0; memset(head,-1,sizeof head); src=1,des=2*nn+2,n=2*nn+2; for(int i=1;i<=nn;i++){ adde(src,i+1,now[i]); adde(i+nn+1,des,need[i]); } for(int i=1;i<=nn;i++){ for(int j=1;j<=nn;j++){ if(dis[i][j]<=c) adde(i+1,j+nn+1,INF); } } } void solve(){ ll l=0,r=maxr; build(r); if(sap()<sum){ printf("-1\n"); return; } while(l<r){ ll mid=(l+r)/2; build(mid); if(sap()>=sum) r=mid; else l=mid+1; } cout<<r<<endl; } int main(){ scanf("%d%d",&nn,&m); initial(); input(); solve(); return 0; }
#include <iostream> #include <cstdio> #include <cstring> #include <queue> using namespace std; const int INF=1000000000; const int maxn=500,maxm=500000; struct edge{ int u,v,f,next; }e[maxm*2+10]; int n,src,sink,cnt,head[maxn+10]; void adde(int u,int v,int f){ e[cnt].u=u,e[cnt].v=v,e[cnt].f=f,e[cnt].next=head[u],head[u]=cnt++; e[cnt].u=v,e[cnt].v=u,e[cnt].f=0,e[cnt].next=head[v],head[v]=cnt++; } void init(){ memset(head,-1,sizeof(head)); cnt=0; } queue <int> q; bool visited[maxn+10]; int dist[maxn+10]; void bfs(){ memset(dist,0,sizeof(dist)); while(!q.empty()) q.pop(); visited[src]=true; q.push(src); while(!q.empty()){ int s=q.front(); q.pop(); for(int i=head[s];i!=-1;i=e[i].next){ int d=e[i].v; if(e[i].f>0 && !visited[d]){ q.push(d); dist[d]=dist[s]+1; visited[d]=true; } } } } int dfs(int u,int delta){ if(u==sink) return delta; else{ int ret=0; for(int i=head[u];delta && i!=-1;i=e[i].next){ if(e[i].f>0 && dist[e[i].v]==dist[u]+1){ int d=dfs(e[i].v,min(e[i].f,delta)); e[i].f-=d; e[i^1].f+=d; delta-=d; ret+=d; } } return ret; } } int maxflow(){ int ret=0; while(true){ memset(visited,false,sizeof(visited)); bfs(); if(!visited[sink]) return ret; ret+=dfs(src,INF); } return ret; } typedef long long ll; const ll inf=2e18; int nn,m,now[maxn],need[maxn],sum; ll dis[maxn][maxn],maxr; void initial(){ sum=0; for(int i=0;i<=nn;i++){ for(int j=0;j<=nn;j++){ if(i!=j) dis[i][j]=inf; else dis[i][j]=0; } } } void input(){ for(int i=1;i<=nn;i++){ scanf("%d%d",&now[i],&need[i]); sum+=now[i]; } for(int i=0;i<m;i++){ int u,v,x; scanf("%d%d%d",&u,&v,&x); if(x<dis[u][v]){ dis[u][v]=dis[v][u]=x; } } for(int k=1;k<=nn;k++){ for(int i=1;i<=nn;i++){ for(int j=1;j<=nn;j++){ if(dis[i][k]+dis[k][j]<dis[i][j]) dis[i][j]=dis[i][k]+dis[k][j]; } } } maxr=0; for(int i=1;i<=nn;i++){ for(int j=1;j<=nn;j++){ if(dis[i][j]!=inf && dis[i][j]>maxr) maxr=dis[i][j]; } } } void build(ll c){ init(); src=1,sink=2*nn+2,n=2*nn+2; for(int i=1;i<=nn;i++){ adde(src,i+1,now[i]); adde(i+nn+1,sink,need[i]); } for(int i=1;i<=nn;i++){ for(int j=1;j<=nn;j++){ if(dis[i][j]<=c) adde(i+1,j+nn+1,INF); } } } void solve(){ ll l=0,r=maxr; build(r); if(maxflow()<sum){ printf("-1\n"); return; } while(l<r){ ll mid=(l+r)/2; build(mid); if(maxflow()>=sum) r=mid; else l=mid+1; } cout<<r<<endl; } int main(){ scanf("%d%d",&nn,&m); initial(); input(); solve(); return 0; }
#include <iostream> #include <cstdio> #include <cstring> #include <queue> using namespace std; typedef long long ll; const ll inf=1e18; const int maxn=1100; struct edge{ int u,v,next,f; edge(int u0=0,int v0=0,int f0=0,int next0=0){ u=u0,v=v0,f=f0,next=next0; } }e[maxn*maxn]; int head[maxn*2],visited[maxn*2],path[maxn*2]; int cnt,from,to,marked; int n,m,now[maxn],need[maxn],sum; ll dis[maxn][maxn],maxr; void initial(){ sum=0; for(int i=0;i<=n;i++){ for(int j=0;j<=n;j++){ dis[i][j]=inf; } dis[i][i]=0; } } void input(){ for(int i=1;i<=n;i++){ scanf("%d%d",&now[i],&need[i]); sum+=now[i]; } for(int i=0;i<m;i++){ int u,v; ll x; scanf("%d%d%lld",&u,&v,&x); maxr+=x; if(x<dis[u][v]){ dis[u][v]=dis[v][u]=x; } } for(int k=1;k<=n;k++){ for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ if(dis[i][k]+dis[k][j]<dis[i][j]) dis[i][j]=dis[i][k]+dis[k][j]; } } } } void adde(int u,int v,int f){ e[cnt].u=u,e[cnt].v=v,e[cnt].f=f,e[cnt].next=head[u],head[u]=cnt++; e[cnt].u=v,e[cnt].v=u,e[cnt].f=0,e[cnt].next=head[v],head[v]=cnt++; } bool bfs(){ int s=from,d; queue <int> q; q.push(s); marked++; visited[s]=marked; while(!q.empty()){ s=q.front(); q.pop(); for(int i=head[s];i!=-1;i=e[i].next){ d=e[i].v; if(visited[d]!=marked && e[i].f>0){ visited[d]=marked; path[d]=i; q.push(d); if(d==to) return true; } } } return false; } int maxf(){ int maxflow=0; while(bfs() ){ int flow=maxn; for(int i=to;i!=from;i=e[path[i]].u){ flow=min(e[path[i]].f,flow); } for(int i=to;i!=from;i=e[path[i]].u){ e[path[i]].f-=flow; e[path[i]^1].f+=flow; } maxflow+=flow; } return maxflow; } void build(ll c){ cnt=0; marked=1; memset(head,-1,sizeof(head)); memset(visited,0,sizeof(visited)); from=0,to=2*n+1; for(int i=1;i<=n;i++){ adde(from,i,now[i]); adde(i+n,to,need[i]); } for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ if(dis[i][j]<=c) adde(i,j+n,(1<<30)); } } maxr=0; for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ if(dis[i][j]!=inf && dis[i][j]>maxr) maxr=dis[i][j]; } } } void solve(){ ll l=0,r=maxr; build(r); if(maxf()<sum){ printf("-1\n"); return; } while(l<r){ ll mid=(l+r)/2; build(mid); if(maxf()>=sum) r=mid; else l=mid+1; } cout<<r<<endl; } int main(){ scanf("%d%d",&n,&m); initial(); input(); solve(); return 0; }
POJ 2391 Ombrophobic Bovines (二分,最短路径,网络流sap,dinic,预留推进 ),布布扣,bubuko.com
POJ 2391 Ombrophobic Bovines (二分,最短路径,网络流sap,dinic,预留推进 )
原文:http://blog.csdn.net/a1061747415/article/details/28723685