网络流板子/费用流板子 2018南京I题+2016青岛G题
2018南京I题:
dinic,链式前向星,数组队列,当前弧优化,不memset全部数组,抛弃满流点,bfs只找一条增广路,每次多路增广
#include <bits/stdc++.h> #define ll long long #define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0) #define rep(ii,a,b) for(int ii=a;ii<=b;++ii) using namespace std; const int maxn=2e3+10,maxm=2e6+10; const int INF=0x3f3f3f3f; const int mod=1e9+7; const double PI=acos(-1.0); //head int casn,n,m,k; class mxf{public: struct node{int to,next;ll cap;}e[maxm<<1]; int cur[maxn],head[maxn],que[maxn],dis[maxn],nume=1,s,t; inline void adde(int a,int b,ll c){e[++nume]={b,head[a],c};head[a]=nume;} inline void add(int a,int b,ll c){adde(a,b,c);adde(b,a,0);} void init(int n=maxn-1){memset(head,0,(n+1)<<2);nume=1;} bool bfs(){ memset(dis,-1,(t+1)<<2); dis[t]=0,que[0]=t; int tp=0,ed=1; while(tp!=ed){ int now=que[tp++];tp%=maxn; for(int i=head[now];i;i=e[i].next){ int to=e[i].to; if(dis[to]==-1&&e[i^1].cap){ dis[to]=dis[now]+1; if(to==s) return true; que[ed++]=to;ed%=maxn; } } } return false; } ll dfs(int now,ll flow=0x3f3f3f3f){ if(now==t||flow==0) return flow; ll use=0; for(int &i=head[now];i&&use!=flow;i=e[i].next){ int to=e[i].to; if(dis[to]+1!=dis[now])continue; ll tmp=dfs(to,min(e[i].cap,flow-use)); e[i].cap-=tmp,e[i^1].cap+=tmp,use+=tmp; } if(!use) dis[now]=-1; return use; } ll getflow(int ss,int tt){ s=ss,t=tt;ll ans=0; memcpy(cur,head,(t+1)<<2); while(bfs()){ ans+=dfs(s); memcpy(head,cur,(t+1)<<2); } return ans; } }net; int main() {IO; cin>>n>>m>>k; int s=n+m+1,t=n+m+10,ss=n+m+2; net.init(t);net.add(s,ss,k); rep(i,1,n){ net.add(s,i,1);net.add(ss,i,1); int x;cin>>x; while(x--){ int y;cin>>y; net.add(i,n+y,1); } } while(m--) net.add(n+m+1,t,1); cout<<net.getflow(s,t); return 0; }
2016青岛G
原始对偶算法+dijkstra正权化
#include <bits/stdc++.h> #define endl '\n' #define ll long long #pragma GCC optimize("Ofast") #define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0) #define rep(ii,a,b) for(int ii=a;ii<=b;++ii) using namespace std; const int maxn=2e3+10,maxm=2e6+10; const double eps=1e-4; int casn,n,m,k; class mcf{public: #define tpp double struct node{int to;ll cap;tpp cost;int rev;}; int prev[maxn],pree[maxn]; tpp dis[maxn],cost,h[maxn]; ll f; vector<node> g[maxn]; void init(int n=maxn-2){rep(i,0,n+1) g[i].clear();} inline void add(int from,int to,ll cap,tpp cost){ g[from].push_back({to,cap,cost,(int)g[to].size()}); g[to].push_back({from,0,-cost,(int)g[from].size()}); } tpp getcost(int s,int t){ f=0,cost=0; fill(h,h+1+t,0); while(1){ #define pdi pair<tpp,int> priority_queue<pdi,vector<pdi>,greater<pdi> >que; fill(dis,dis+t+1,1e10); dis[s]=0;que.push(make_pair(0,s)); while(!que.empty()){ auto now=que.top();que.pop(); if(dis[now.second]<now.first)continue; int x=now.second; int cnt=0; for(auto &i:g[x]) if(i.cap>0&&dis[i.to]>eps+dis[x]+h[x]-h[i.to]+i.cost){ dis[i.to]=dis[x]+i.cost+h[x]-h[i.to]; prev[i.to]=x; pree[i.to]=cnt++; que.push(make_pair(dis[i.to],i.to)); }else cnt++; } if(dis[t]>=1e9)break; rep(i,0,t) h[i]+=dis[i]; ll d=1e9; for(int now=t;now!=s;now=prev[now]) d=min(d,g[prev[now]][pree[now]].cap); if(d==1e9)break; f+=d;cost+=d*h[t]; for(int now=t;now!=s;now=prev[now]){ node &e=g[prev[now]][pree[now]]; e.cap-=d,g[now][e.rev].cap+=d; } } return cost; } }net; int a[maxn],b[maxn]; int main() {IO; cout<<fixed<<setprecision(2); cin>>casn; while(casn--){ cin>>n>>m; int s=n+1,t=n+2; net.init(t); rep(i,1,n){ cin>>a[i]>>b[i]; int k=min(a[i],b[i]); a[i]-=k,b[i]-=k; if(a[i])net.add(s,i,a[i],0); if(b[i])net.add(i,t,b[i],0); } while(m--){ int x,y,z;double p; cin>>x>>y>>z>>p; p=-log(1-p); if(z>0) net.add(x,y,1,0); if(z>1) net.add(x,y,z-1,p); } double ans=1.0-exp(-net.getcost(s,t)); cout<<ans<<endl; } return 0; }
EK+spfa
#include <bits/stdc++.h> #define endl '\n' #define ll long long #define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0) #define rep(ii,a,b) for(int ii=a;ii<=b;++ii) using namespace std; const int maxn=1e3+10,maxm=1e5+10; const double eps=1e-8; int casn,n,m,k; class mcf{public: #define tpp double int nume=1,s,t,mflow; int head[maxn],flow[maxn],pre[maxn]; tpp dis[maxn],mcost; struct node{int to,next,cap;tpp cost;}e[maxm<<1]; void init(int n=maxn-10){ fill(head,head+n+2,0); nume=1,mflow=mcost=0; } inline void add(int from,int to,int cap,tpp cost){ e[++nume]={to,head[from],cap,cost};head[from]=nume; e[++nume]={from,head[to],0,-cost};head[to]=nume; } bool vis[maxn]; queue<int>q; bool spfa(){ fill(dis,dis+2+t,1e9); fill(vis,vis+2+t,false); dis[s]=0;flow[s]=1e9;q.push(s); while (!q.empty()){ int now=q.front();q.pop(); vis[now]=false; for (int i=head[now];i;i=e[i].next){ int to=e[i].to; tpp cost=e[i].cost; if (e[i].cap&&dis[now]+cost+eps<dis[to]){ dis[to]=dis[now]+cost; flow[to]=min(flow[now],e[i].cap); pre[to]=i; if (!vis[to]){ vis[to]=true; q.push(to); } } } } return dis[t]<1e9; } void update(){ int x=t; while (x!=s){ int i=pre[x]; e[i].cap-=flow[t]; e[i^1].cap+=flow[t]; x=e[i^1].to; } mflow+=flow[t]; mcost+=(tpp)flow[t]*dis[t]; } double getcost(int s,int t){ this->s=s;this->t=t; while (spfa())update(); return mcost; } }net; int a[maxn],b[maxn]; int main() {IO; cout<<fixed<<setprecision(2); while(cin>>casn){ while(casn--){ cin>>n>>m; int s=n+1,t=n+2; net.init(t); rep(i,1,n){ cin>>a[i]>>b[i]; int k=min(a[i],b[i]); a[i]-=k,b[i]-=k; if(a[i])net.add(s,i,a[i],0); if(b[i])net.add(i,t,b[i],0); } while(m--){ int x,y,z;double p; cin>>x>>y>>z>>p; p=-log(1-p); if(z>0) net.add(x,y,1,0); if(z>1) net.add(x,y,z-1,p); } double ans=net.getcost(s,t); ans=exp(-ans); ans=1.0-ans; cout<<ans<<endl; } } return 0; }