hdu 4560 網路流+二分
阿新 • • 發佈:2018-12-16
題目思路:
一開始,並不怎麼清楚網路流怎麼寫,一開始用最小費用網路流寫的,怎麼寫都超時,我很奇怪,後來就去找網上網路流的程式碼,詐一看,思路一樣的呀,一樣是dfs+流修改嘛,為啥我的時間這麼長,難道說是我哪裡沒注意???,找了2個小時的超時+看懂網路流,原來網路流只需要所有的邊跑一邊,而最小費用網路流並不是,有些邊需要跑很多遍,傻逼了。同樣,建圖思路也挺厲害的
AC程式碼
#include<bits/stdc++.h> using namespace std; #define maxn 500 #define maxm 100000 #define inf 0x3f3f3f3f int good[maxn][maxn]; int first[maxn]; int edge_num; int lev[maxn]; int vis[maxn]; int N,M,L,K; struct edge{ int u,v; int cap; int next; }e[maxm]; void add_edge(int u,int v,int c) { e[edge_num].u=u; e[edge_num].v=v; e[edge_num].cap=c; e[edge_num].next=first[u]; first[u]=edge_num++; e[edge_num].u=v; e[edge_num].v=u; e[edge_num].cap=0; e[edge_num].next=first[v]; first[v]=edge_num++; } int Dinic_spath(int s,int t) { queue<int>q; q.push(s); memset(lev,-1,sizeof(lev)); memset(vis,0,sizeof(vis)); lev[s]=0; while(!q.empty()) { int u=q.front(); vis[u]=0; q.pop(); for(int k=first[u];k!=-1;k=e[k].next) { int v=e[k].v; if(lev[v]==-1&&e[k].cap>0) { lev[v]=lev[u]+1; if(!vis[v]) { vis[v]=1; q.push(v); } } } } return lev[t]!=-1; } int Dinic_dfs(int u,int t,int flow) { int cost=0; if(u==t) return flow; for(int k=first[u];k!=-1;k=e[k].next) { int v=e[k].v; if(lev[v]==lev[u]+1&&e[k].cap>0) { int minn=Dinic_dfs(v,t,min(e[k].cap,flow-cost)); if(minn>0) { e[k].cap=e[k].cap-minn; e[k^1].cap=e[k^1].cap+minn; cost+=minn; if(cost==flow) break; } else lev[v]=-1; } } return cost; } bool judge(int ans) { memset(first,-1,sizeof(first)); edge_num=0; int s=0; int t=N+2*M+1; for(int i=1;i<=N;++i) add_edge(0,i,ans); for(int i=1;i<=N;++i) { for(int j=1;j<=M;++j) { if(good[i][j]) add_edge(i,N+j,1); else add_edge(i,N+M+j,1); } } for(int i=1;i<=M;++i) add_edge(N+M+i,N+i,K); for(int i=1;i<=M;++i) add_edge(N+i,N+2*M+1,ans); int f=0; while(Dinic_spath(s,t)) { f+=Dinic_dfs(s,t,10000000); } return f>=ans*N; } int main() { int t; scanf("%d",&t); int ca=1; while(t--) { memset(good,0,sizeof(good)); scanf("%d%d%d%d",&N,&M,&L,&K); for(int i=1;i<=L;++i) { int a,b; scanf("%d%d",&a,&b); good[a][b]=1; } int ans; int ansl=0; int ansr=M; int temp=0; while(ansl<=ansr) { ans=(ansl+ansr)/2; if(judge(ans)) { temp=max(temp,ans); ansl=ans+1; } else ansr=ans-1; } printf("Case %d: %d\n",ca++,temp); } }