bzoj1834: [ZJOI2010]network 网络扩容
努力看了很久样例一直过不了。。。然后各种输出中间过程啊巴拉巴拉弄了1h,没办法了。。。然后突然想到啊原来的边可以用啊为什么不用。。。于是A了。。。感人肺腑
#include<cstdio> #include<cstring> #include<queue> #include<iostream> #include<algorithm> using namespace std; #define rep(i,n) for(int i=1;i<=n;i++) #define qwq(x) for(edge *e=head[x];e;e=e->next) #define clr(x,c) memset(x,c,sizeof(x)) #define REP(i,s,t) for(int i=s;i<=t;i++) int read(){ int x=0;char c=getchar();bool f=true; while(!isdigit(c)){ if(c=='-') f=false;c=getchar(); } while(isdigit(c)) x=x*10+c-'0',c=getchar(); return f?x:-x; } const int nmax=1005; const int maxn=20005; const int inf=0x7f7f7f7f; struct edge{ int to,cap,cost;edge *next,*rev; }; edge edges[maxn],*pt,*head[nmax],*cur[nmax],*p[nmax]; int u[maxn],v[maxn],w[maxn]; void add(int u,int v,int d,int w){ pt->to=v;pt->cap=d;pt->cost=w;pt->next=head[u];head[u]=pt++; } void adde(int u,int v,int d,int w){ add(u,v,d,w);add(v,u,0,-w);head[u]->rev=head[v];head[v]->rev=head[u]; } bool inq[nmax]; int h[nmax],cnt[nmax],d[nmax],a[nmax]; int mincost(int s,int t){ int cost=0; while(1){ clr(inq,0);inq[s]=1;clr(d,0x7f);d[s]=0;a[s]=inf; queue<int>q;q.push(s); while(!q.empty()){ int x=q.front();q.pop();inq[x]=0; // printf("%d: %d\n",x,d[x]) ; qwq(x) if(e->cap>0&&d[e->to]>d[x]+e->cost){ int to=e->to;d[to]=d[x]+e->cost; // printf("tmd:%d\n",e->cost); a[to]=min(a[x],e->cap);p[to]=e; if(!inq[to]) q.push(to),inq[to]=1; } } if(d[t]==inf) break; cost+=d[t]*a[t]; int x=t; while(x!=s) p[x]->cap-=a[t],p[x]->rev->cap+=a[t],x=p[x]->rev->to; //printf("%d %d\n",d[t],cost); } return cost; } int maxflow(int s,int t,int n){ clr(cnt,0);cnt[0]=n;clr(h,0); int flow=0,a=inf,x=s;edge *e; while(h[s]<n){ for(e=cur[x];e;e=e->next) if(e->cap>0&&h[e->to]+1==h[x]) break; if(e){ a=min(a,e->cap);p[e->to]=cur[x]=e;x=e->to; if(x==t){ while(x!=s) p[x]->cap-=a,p[x]->rev->cap+=a,x=p[x]->rev->to; flow+=a;a=inf; } }else{ if(!--cnt[h[x]]) break; h[x]=n; for(e=head[x];e;e=e->next) if(e->cap>0&&h[x]>h[e->to]+1) cur[x]=e,h[x]=h[e->to]+1; cnt[h[x]]++; if(x!=s) x=p[x]->rev->to; } } return flow; } int main(){ int n=read(),m=read(),k=read(),sa=1,ta=n,sb=0,tb=n+1,cap; pt=edges;clr(head,0); rep(i,m){ u[i]=read(),v[i]=read(),cap=read(),w[i]=read();adde(u[i],v[i],cap,0); } /*rep(i,n) { qwq(i) printf("%d %d %d\n",e->to,e->cap,e->cost); printf("\n"); }*/ printf("%d ",maxflow(sa,ta,n)); // pt=edges;clr(head,0); rep(i,m) adde(u[i],v[i],k,w[i]); adde(sb,sa,k,0);adde(ta,tb,k,0); /* REP(i,0,n) { qwq(i) printf("%d %d %d\n",e->to,e->cap,e->cost); printf("\n"); }*/ printf("%d\n",mincost(sb,tb)); return 0; }
1834: [ZJOI2010]network 网络扩容
Time Limit: 3 Sec Memory Limit: 64 MBSubmit: 2628 Solved: 1333
[Submit][Status][Discuss]
Description
给定一张有向图,每条边都有一个容量C和一个扩容费用W。这里扩容费用是指将容量扩大1所需的费用。求: 1、 在不扩容的情况下,1到N的最大流; 2、 将1到N的最大流增加K所需的最小扩容费用。
Input
输入文件的第一行包含三个整数N,M,K,表示有向图的点数、边数以及所需要增加的流量。 接下来的M行每行包含四个整数u,v,C,W,表示一条从u到v,容量为C,扩容费用为W的边。
Output
输出文件一行包含两个整数,分别表示问题1和问题2的答案。
Sample Input
5 8 2
1 2 5 8
2 5 9 9
5 1 6 2
5 1 1 8
1 2 8 7
2 5 4 9
1 2 1 1
1 4 2 1
1 2 5 8
2 5 9 9
5 1 6 2
5 1 1 8
1 2 8 7
2 5 4 9
1 2 1 1
1 4 2 1
Sample Output
13 19
30%的数据中,N<=100
100%的数据中,N<=1000,M<=5000,K<=10
30%的数据中,N<=100
100%的数据中,N<=1000,M<=5000,K<=10