标签:des c style class blog code
| 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,预留推进 )
标签:des c style class blog code
原文地址:http://blog.csdn.net/a1061747415/article/details/28723685