BZOJ 1834网络扩容题解
一道不算太难的题目
但是真的很恶心
显然,对于第一问,我们直接无脑打模板就好了
第二问也不是很难,我们将每条边再连一条容量为inf,费用为w的边
但是流量只要小于第一问的答案加k就行了
所以我们增加一个点为第二问的汇点,将n与它连接一条容量为ans+k,费用为0的边
跑费用流就好了
但是!!!!!!!
这样作只有40分,为什么呢。
因为虽然数据范围说n<=1000但给的点编号有大于1000的点。。。。。
我们只要将点数视为5000就可以过来了
真的恶心。。。。
不过在考场上还是建议用离散化,毕竟你不知道点数编号的范围
想问一问当初省选时有多少人被这个给坑了。。
# include<iostream> # include<cstdio> # include<cmath> # include<algorithm> # include<cstring> # include<queue> using namespace std; const int mn = 5005; const int inf = 0xfffffff; struct edge{ int to,next,flow,cup,cost; edge(){to=flow=cup=cost=0,next=-1;} }; edge e[mn*10]; int head[mn],edge_max=-1; void add(int x,int y,int k,double c) { e[++edge_max].to=y; e[edge_max].next=head[x]; e[edge_max].flow=e[edge_max].cup=k; e[edge_max].cost=c; head[x]=edge_max; } int n,m,k; int ans1,ans2; int deep[mn]; int cur[mn]; queue<int> q; bool bfs(int x,int y) { memset(deep,0,sizeof(deep)); q.push(x); deep[x]=1; while(!q.empty()) { int u=q.front(); q.pop(); for(int i=head[u];i!=-1;i=e[i].next) { if(deep[e[i].to]==0 && e[i].flow>0 ) { deep[e[i].to]=deep[u]+1; q.push(e[i].to); } } } if(deep[y]==0) return false; else return true; } int dfs(int x,int dist,int y) { if(x==y) return dist; for(int &i=cur[x];i!=-1;i=e[i].next) { if(deep[e[i].to]==deep[x]+1 && e[i].flow!=0) { int di=dfs(e[i].to,min(dist,e[i].flow),y); if(di>0) { e[i].flow-=di; e[i^1].flow+=di; return di; } } } return 0; } void dinic(int x,int y) { while(bfs(x,y)) { for(int i=1;i<=n;i++) cur[i]=head[i]; while(int k=dfs(x,inf,y)) ans1+=k; } } int dis[mn]; int pe[mn],pv[mn]; bool vis[mn]; bool spfa(int x,int y) { memset(vis,0,sizeof(vis)); for(int i=1;i<=n+1;i++) dis[i]=inf; dis[x]=0; vis[x]=1; q.push(x); while(!q.empty()) { int u=q.front(); q.pop(); vis[u]=0; for(int i=head[u];i!=-1;i=e[i].next) { if(dis[u]+e[i].cost<dis[e[i].to] && e[i].flow>0) { dis[e[i].to]=e[i].cost+dis[u]; pe[e[i].to]=i; pv[e[i].to]=u; if(!vis[e[i].to]) { q.push(e[i].to); vis[e[i].to]=1; } } } } if(dis[y]!=inf) return true; else return false; } void max_flow(int x,int y) { while(spfa(x,y)) { int mflow=inf; for(int i=y;i!=x;i=pv[i]) { mflow=min(mflow,e[pe[i]].flow); } ans2+=dis[y]*mflow; for(int i=y;i!=x;i=pv[i]) { e[pe[i]].flow-=mflow; e[pe[i]^1].flow+=mflow; } } } int a1[mn],a2[mn],a3[mn],a4[mn]; void pre() { memset(head,-1,sizeof(head)); memset(e,-1,sizeof(e)); for(int i=1;i<=m;i++) { add(a1[i],a2[i],a3[i],0); add(a2[i],a1[i],0,0); add(a1[i],a2[i],inf,a4[i]); add(a2[i],a1[i],0,-a4[i]); } } int main() { int x,y,c,w; memset(head,-1,sizeof(head)); scanf("%d%d%d",&n,&m,&k); for(int i=1;i<=m;i++) { scanf("%d%d%d%d",&a1[i],&a2[i],&a3[i],&a4[i]); add(a1[i],a2[i],a3[i],0); add(a2[i],a1[i],0,0); } dinic(1,n); pre(); add(n,n+1,ans1+k,0); add(n+1,n,0,0); max_flow(1,n+1); printf("%d %d",ans1,ans2); return 0; }