-
3041 Asteroids (5)
-
2195 Going Home (6)
-
3281 Dining (7)
-
2391 Ombrophobic Bovines (8, challenge problem)
-
3498 March of the Penguins (8, challenge problem)
poj2195
最小费用二分图匹配的三种方式
#include <cmath> #include <vector> #include <iostream> #include <cstdio> #include <cstring> #include <queue> using namespace std; typedef vector<int> VI; typedef vector<VI> VVI; typedef long long L; typedef vector<L> VL; typedef vector<VL> VVL; typedef pair<int, int> PII; typedef vector<PII> VPII; typedef vector<double> VD; typedef vector<VD> VVD; const L INF = 0x3f3f3f3f; struct MinCostMaxFlow { int N; VVL cap, flow, cost; VI found; VL dist, pi, width; VPII dad; MinCostMaxFlow(int N) : N(N), cap(N, VL(N)), flow(N, VL(N)), cost(N, VL(N)), found(N), dist(N), pi(N), width(N), dad(N) {} void AddEdge(int from, int to, L cap, L cost) { this->cap[from][to] = cap; this->cost[from][to] = cost; } void Relax(int s, int k, L cap, L cost, int dir) { L val = dist[s] + pi[s] - pi[k] + cost; if (cap && val < dist[k]) { dist[k] = val; dad[k] = make_pair(s, dir); width[k] = min(cap, width[s]); } } L Dijkstra(int s, int t) { fill(found.begin(), found.end(), false); fill(dist.begin(), dist.end(), INF); fill(width.begin(), width.end(), 0); dist[s] = 0; width[s] = INF; while (s != -1) { int best = -1; found[s] = true; for (int k = 0; k < N; k++) { if (found[k]) continue; Relax(s, k, cap[s][k] - flow[s][k], cost[s][k], 1); Relax(s, k, flow[k][s], -cost[k][s], -1); if (best == -1 || dist[k] < dist[best]) best = k; } s = best; } for (int k = 0; k < N; k++) pi[k] = min(pi[k] + dist[k], INF); return width[t]; } pair<L, L> GetMaxFlow(int s, int t) { L totflow = 0, totcost = 0; while (L amt = Dijkstra(s, t)) { totflow += amt; for (int x = t; x != s; x = dad[x].first) { if (dad[x].second == 1) { flow[dad[x].first][x] += amt; totcost += amt * cost[dad[x].first][x]; } else { flow[x][dad[x].first] -= amt; totcost -= amt * cost[x][dad[x].first]; } } } return make_pair(totflow, totcost); } }; int ht,mt; char mat[110][110]; typedef pair<int,int> pii; pii house[110],man[110]; int dis(int i,int j){ return abs(house[i].first-man[j].first)+abs(house[i].second-man[j].second); } void gao_mcmf(){ MinCostMaxFlow my(ht+ht+2); for(int i=0;i<ht;++i){ my.AddEdge(0,i+1,1,0); my.AddEdge(i+ht+1,ht+ht+1,1,0); for(int j=0;j<ht;++j){ my.AddEdge(i+1,ht+j+1,1,dis(i,j)); } } printf("%lld\n",my.GetMaxFlow(0,ht+ht+1).second); } // double MinCostMatching(const VVD &cost, VI &Lmate, VI &Rmate) { int n = int(cost.size()); // construct dual feasible solution VD u(n); VD v(n); for (int i = 0; i < n; i++) { u[i] = cost[i][0]; for (int j = 1; j < n; j++) u[i] = min(u[i], cost[i][j]); } for (int j = 0; j < n; j++) { v[j] = cost[0][j] - u[0]; for (int i = 1; i < n; i++) v[j] = min(v[j], cost[i][j] - u[i]); } // construct primal solution satisfying complementary slackness Lmate = VI(n, -1); Rmate = VI(n, -1); int mated = 0; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (Rmate[j] != -1) continue; if (fabs(cost[i][j] - u[i] - v[j]) < 1e-10) { Lmate[i] = j; Rmate[j] = i; mated++; break; } } } VD dist(n); VI dad(n); VI seen(n); // repeat until primal solution is feasible while (mated < n) { // find an unmatched left node int s = 0; while (Lmate[s] != -1) s++; // initialize Dijkstra fill(dad.begin(), dad.end(), -1); fill(seen.begin(), seen.end(), 0); for (int k = 0; k < n; k++) dist[k] = cost[s][k] - u[s] - v[k]; int j = 0; while (true) { // find closest j = -1; for (int k = 0; k < n; k++) { if (seen[k]) continue; if (j == -1 || dist[k] < dist[j]) j = k; } seen[j] = 1; // termination condition if (Rmate[j] == -1) break; // relax neighbors const int i = Rmate[j]; for (int k = 0; k < n; k++) { if (seen[k]) continue; const double new_dist = dist[j] + cost[i][k] - u[i] - v[k]; if (dist[k] > new_dist) { dist[k] = new_dist; dad[k] = j; } } } // update dual variables for (int k = 0; k < n; k++) { if (k == j || !seen[k]) continue; const int i = Rmate[k]; v[k] += dist[k] - dist[j]; u[i] -= dist[k] - dist[j]; } u[s] += dist[j]; // augment along path while (dad[j] >= 0) { const int d = dad[j]; Rmate[j] = Rmate[d]; Lmate[Rmate[j]] = j; j = d; } Rmate[j] = s; Lmate[s] = j; mated++; } double value = 0; for (int i = 0; i < n; i++) value += cost[i][Lmate[i]]; return value; } VI Lmate,Rmate; void gao_mcmatch(){ VD temp(ht,0); VVD cost(ht,temp); for(int i=0;i<ht;++i){ for(int j=0;j<ht;++j){ cost[i][j]=dis(i,j); } } printf("%.0f\n",MinCostMatching(cost,Lmate,Rmate)); } #define maxn 210 struct NODE{ NODE(){} NODE(int uu,int vv,int cc,int ww,int pp):u(uu),v(vv),c(cc),w(ww),p(pp){} int u,v,c,w,p; }; vector<NODE> adj[maxn],nu; vector<NODE>::iterator pre[maxn]; queue<int> q; int cnt[maxn]; int d[maxn]; bool vis[maxn]; void add(int u,int v,int c,int w){ adj[u].push_back(NODE(u,v,c,w,adj[v].size())); adj[v].push_back(NODE(v,u,0,-w,adj[u].size()-1)); } int n; int spfa(){ while(!q.empty()) q.pop(); fill(d,d+n+2,INF); memset(cnt,0,sizeof(cnt)); memset(vis,0,sizeof(vis)); d[0]=0; cnt[0]=1; vis[0]=1; pre[0]=nu.begin(); q.push(0); int u,v,c; vector<NODE>::iterator it; while(!q.empty()){ u=q.front(); q.pop(); vis[u]=0; for(it=adj[u].begin();it!=adj[u].end();++it){ v=it->v; if(it->c && d[v]>d[u]+it->w){ d[v]=d[u]+it->w; pre[v]=it; if(!vis[v]){ if(++cnt[v]>n+1) return 0; vis[v]=1; q.push(v); } } } } if(d[n+1]==INF) return 0; return 1; } int mfmc(){ int ans=0,m; vector<NODE>::iterator it; while(spfa()){ m=INF; for(it=pre[n+1];it!=nu.begin();it=pre[it->u]){ m=min(m,it->c); } for(it=pre[n+1];it!=nu.begin();it=pre[it->u]){ it->c-=m; adj[it->v][it->p].c+=m; } ans+=m*d[n+1]; } return ans; } void gao_mfmc(){ int i,j; n=ht+ht; for(i=0;i<=n+1;++i) adj[i].clear(); for(int i=0;i<ht;++i){ add(0,i+1,1,0); add(i+ht+1,n+1,1,0); for(int j=0;j<ht;++j){ add(i+1,ht+j+1,1,dis(i,j)); } } printf("%d\n",mfmc()); } /// int main(){ int m,n,i,j; while(scanf("%d%d",&m,&n)!=EOF && m){ ht=mt=0; for(i=0;i<m;++i){ scanf("%s",mat[i]); for(j=0;j<n;++j){ if(mat[i][j]=='H') { house[ht].first=i,house[ht].second=j; ++ht; }else if(mat[i][j]=='m'){ man[mt].first=i,man[mt].second=j; ++mt; } } } // gao_mcmf(); // gao_mcmatch(); gao_mfmc(); } return 0; }
poj2516
最大流最小费模板
#include <cmath> #include <vector> #include <iostream> #include <cstdio> #include <cstring> #include <queue> using namespace std; #define INF 0x3f3f3f3f #define maxn 110 int cost[55][55][55]; int buy[55][55],sell[55][55],bt[55],st[55]; struct NODE{ NODE(){} NODE(int uu,int vv,int cc,int ww,int pp):u(uu),v(vv),c(cc),w(ww),p(pp){} int u,v,c,w,p; }; vector<NODE> adj[maxn],nu; vector<NODE>::iterator pre[maxn]; queue<int> q; int cnt[maxn]; int d[maxn]; bool vis[maxn]; void add(int u,int v,int c,int w){ adj[u].push_back(NODE(u,v,c,w,adj[v].size())); adj[v].push_back(NODE(v,u,0,-w,adj[u].size()-1)); } int n,B,S,K; int spfa(){ while(!q.empty()) q.pop(); fill(d,d+n+2,INF); memset(cnt,0,sizeof(cnt)); memset(vis,0,sizeof(vis)); d[0]=0; cnt[0]=1; vis[0]=1; pre[0]=nu.begin(); q.push(0); int u,v,c; vector<NODE>::iterator it; while(!q.empty()){ u=q.front(); q.pop(); vis[u]=0; for(it=adj[u].begin();it!=adj[u].end();++it){ v=it->v; if(it->c && d[v]>d[u]+it->w){ d[v]=d[u]+it->w; pre[v]=it; if(!vis[v]){ if(++cnt[v]>n+1) return 0; vis[v]=1; q.push(v); } } } } if(d[n+1]==INF) return 0; return 1; } int mfmc(){ int ans=0,m; vector<NODE>::iterator it; while(spfa()){ m=INF; for(it=pre[n+1];it!=nu.begin();it=pre[it->u]){ m=min(m,it->c); } for(it=pre[n+1];it!=nu.begin();it=pre[it->u]){ it->c-=m; adj[it->v][it->p].c+=m; } ans+=m*d[n+1]; } return ans; } int gao_mfmc(int k){ int i,j; for(i=0;i<=n+1;++i) adj[i].clear(); for(i=0;i<S;++i){ add(0,i+1,sell[k][i],0); } for(i=0;i<B;++i){ add(i+S+1,n+1,buy[k][i],0); } for(i=0;i<B;++i){ for(j=0;j<S;++j){ add(j+1,i+S+1,INF,cost[k][i][j]); } } return mfmc(); } int main(){ int i,j,k; while(scanf("%d%d%d",&B,&S,&K)!=EOF && B){ n=B+S; memset(bt,0,sizeof(bt)); memset(st,0,sizeof(st)); for(i=0;i<B;++i){ for(j=0;j<K;++j){ scanf("%d",&buy[j][i]); bt[j]+=buy[j][i]; } } for(i=0;i<S;++i){ for(j=0;j<K;++j){ scanf("%d",&sell[j][i]); st[j]+=sell[j][i]; } } for(k=0;k<K;++k){ for(i=0;i<B;++i){ for(j=0;j<S;++j){ scanf("%d",&cost[k][i][j]); } } } int ok=1; for(i=0;i<K;++i){ if(bt[i]>st[i]){ ok=0; break; } } if(!ok){ printf("-1\n"); continue; } int ans=0; for(i=0;i<K;++i){ ans+=gao_mfmc(i); } printf("%d\n",ans); } return 0; }
poj2226以连续线段为结点,最大二分匹配(匈牙利算法)
#include<cstdio> #include<cstring> #define maxn 1300 int mat[maxn][maxn],match[maxn]; bool vis[maxn]; char map[55][55]; int r[55][55],c[55][55]; int cntr,cntc; int m,n; bool dfs(int i){ int j; for(j=0;j<cntc;++j){ if(!mat[i][j] || vis[j]) continue; vis[j]=1; if(match[j]==-1 || dfs(match[j])){ match[j]=i; return 1; } } return 0; } int main(){ // freopen("d.in","r",stdin); int i,j,ans=0; memset(match,-1,sizeof(match)); scanf("%d%d",&m,&n); for(i=0;i<m;++i){ scanf("%s",map[i]); map[i][n]='.'; } for(i=0;i<n;++i) map[m][i]='.'; for(i=0;i<m;++i){ for(j=0;j<=n;++j){ if(map[i][j]=='*') r[i][j]=cntr; else if(j>0 && map[i][j-1]=='*') ++cntr; } } for(j=0;j<n;++j){ for(i=0;i<=m;++i){ if(map[i][j]=='*') c[i][j]=cntc; else if(i>0 && map[i-1][j]=='*') ++cntc; } } for(i=0;i<m;++i){ for(j=0;j<n;++j){ if(map[i][j]=='*'){ mat[r[i][j]][c[i][j]]=1; } } } for(i=0;i<cntr;++i){ memset(vis,0,sizeof(vis)); if(dfs(i)) ++ans; } printf("%d\n",ans); return 0; }
poj2391floyd+离散化+二分+dinic
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<queue> using namespace std; typedef long long u64; typedef int type; #define maxn 205 #define maxm 81205 #define INF 0x3ffffffffffffLL #define inf 0x3f3f3f3f struct EDGE{ int v,next; type c; }edge[maxm]; u64 mat[maxn][maxn]; int n,N,M; int have[maxn],hold[maxn]; int d[maxn<<1],head[maxn<<1]; int src,des,tot,all; void init(){ memset(head,-1,sizeof(head)); tot=0; } void add(int u,int v,type c){ edge[tot].v=v,edge[tot].c=c,edge[tot].next=head[u];head[u]=tot++; edge[tot].v=u,edge[tot].c=0,edge[tot].next=head[v];head[v]=tot++; } queue<int> q; bool bfs(){ while(!q.empty()) q.pop(); int u,v,i; type c; memset(d,-1,sizeof(d)); d[src]=0; q.push(src); while(!q.empty()){ u=q.front(); q.pop(); for(i=head[u];i!=-1;i=edge[i].next){ v=edge[i].v; c=edge[i].c; if(c>0 && d[v]==-1){ d[v]=d[u]+1; q.push(v); } } } return (d[des]!=-1); } type dfs(int u,type mm){ if(u==des) return mm; int i,v; type c,temp; for(i=head[u];i!=-1;i=edge[i].next){ v=edge[i].v; c=edge[i].c; if(c>0 && d[v]==d[u]+1 && (temp=dfs(v,min(mm,c)))){ edge[i].c-=temp; edge[i^1].c+=temp; return temp; } } d[u]=-1; return 0; } type dinic(){ type ans=0,temp; while(bfs()){ while(1){ temp=dfs(src,inf); if(!temp) break; ans+=temp; } } return ans; } bool check(u64 k){ int i,j; init(); for(i=1;i<=N;++i){ for(j=1;j<=N;++j){ if(mat[i][j]<=k && i!=j && have[i]){ add(i,j+N,have[i]); } } if(have[i]){ add(i,N+i,have[i]); add(src,i,have[i]); } if(hold[i]){ add(i+N,des,hold[i]); } } if(dinic()==all) return 1; return 0; } u64 h[maxn*maxn]; int cnt; int main(){ //freopen("data.in","r",stdin);//freopen("data.out","w",stdout); int i,j,u,v,k,l,r,m; u64 c; scanf("%d%d",&N,&M); for(i=1;i<=N;++i){ scanf("%d%d",&have[i],&hold[i]); all+=have[i]; for(j=1;j<=N;++j) mat[i][j]=INF; } while(M--){ scanf("%d%d%lld",&u,&v,&c); mat[u][v]=min(mat[u][v],c); mat[v][u]=min(mat[v][u],c); } for(k=1;k<=N;++k){ for(i=1;i<=N;++i){ for(j=1;j<=N;++j){ mat[i][j]=min(mat[i][j],mat[i][k]+mat[k][j]); } } } cnt=1; for(i=1;i<=N;++i){ for(j=i+1;j<=N;++j){ if(mat[i][j]!=INF){ h[cnt++]=mat[i][j]; } } } n=N+N+2; src=0,des=n-1; sort(h,h+cnt); cnt=unique(h,h+cnt)-h; l=0,r=cnt-1; if(!check(h[r])){ printf("-1\n"); return 0; } while(l+1<r){ m=(l+r)>>1; // printf("l=%d r=%d h[m]=%lld\n",l,r,h[m]); if(check(h[m])) r=m; else l=m; } printf("%lld\n",h[r]); return 0; }
Assignment 8: Network Flow Problems
最新推荐文章于 2022-06-03 21:28:38 发布