标签:why pop 模型 java tar pos integer turn ted
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2650 Accepted Submission(s): 1411
//费用流模板题,因为题目中的表述就是一个网络流模型,拆点建图,没点只经过一次,起点终点容量为2, //其他点容量为1,要求最大费用费用为负权值,套模板。起点和终点经历了两次,最后要减去。 /****************最小费用最大流模板,白书363页*******************************/ #include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<vector> using namespace std; const int maxn=30*30*2+5,inf=0x7fffffff;//本体拆点,数组多开两倍 struct Edge { int from,to,cap,flow,cost; Edge(int u,int v,int c,int f,int cs):from(u),to(v),cap(c),flow(f),cost(cs){} }; struct MCMF { int n,m,s,t; vector<Edge>edges; vector<int>g[maxn]; int inq[maxn],d[maxn],p[maxn],a[maxn]; void init(int n) { this->n=n; for(int i=0;i<n;i++) g[i].clear(); edges.clear(); } void AddEdge(int from,int to,int cap,int cost) { edges.push_back((Edge){from,to,cap,0,cost}); edges.push_back((Edge){to,from,0,0,-cost}); m=edges.size(); g[from].push_back(m-2); g[to].push_back(m-1); } bool BellmanFord(int s,int t,int &flow,int &cost) { for(int i=0;i<n;i++) d[i]=inf; memset(inq,0,sizeof(inq)); d[s]=0;inq[s]=1;p[s]=0;a[s]=inf; queue<int>q; q.push(s); while(!q.empty()){ int u=q.front();q.pop(); inq[u]=0; for(int i=0;i<(int)g[u].size();i++){ Edge &e=edges[g[u][i]]; if(e.cap>e.flow&&d[e.to]>d[u]+e.cost){ d[e.to]=d[u]+e.cost; p[e.to]=g[u][i]; a[e.to]=min(a[u],e.cap-e.flow); if(!inq[e.to]) {q.push(e.to);inq[e.to]=1;} } } } if(d[t]==inf) return false; flow+=a[t]; cost+=d[t]*a[t]; int u=t; while(u!=s){ edges[p[u]].flow+=a[t]; edges[p[u]^1].flow-=a[t]; u=edges[p[u]].from; } return true; } int Mincost(int s,int t) { int flow=0,cost=0; while(BellmanFord(s,t,flow,cost)); return cost;//返回最小费用,flow存最大流 } }MC; /**********************************************************************************/ int main() { int n,mp[35][35]; while(scanf("%d",&n)==1){ int s=0,t=n*n*2+1; MC.init(n*n*2+2); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%d",&mp[i][j]); for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ int id=(i-1)*n+j; if(id==1){ MC.AddEdge(id,id+n*n,2,-mp[i][j]); MC.AddEdge(s,id,2,0); } else if(id==n*n){ MC.AddEdge(id,id+n*n,2,-mp[i][j]); MC.AddEdge(id+n*n,t,2,0); } else MC.AddEdge(id,id+n*n,1,-mp[i][j]); if(i<n){ int nid=id+n; MC.AddEdge(id+n*n,nid,1,0); } if(j<n){ int nid=id+1; MC.AddEdge(id+n*n,nid,1,0); } } } int ans=-(MC.Mincost(0,n*n*2+1)+mp[1][1]+mp[n][n]); printf("%d\n",ans); } return 0; }
Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 102400/102400 K (Java/Others)
Total Submission(s): 4255 Accepted Submission(s): 1233
//和HDU2686一样,只是数据变大了,上一个模板会超内存,这个板不会。 /***********************最小费用最大流模板2*************************/ #include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; const int maxn=610*610*2+2; const int maxm=4*maxn;//!边数要够 const int inf=0x7fffffff; struct Edge { int to,next,cap,flow,cost; }edges[maxm]; int head[maxn],tol,pre[maxn],dis[maxn]; bool vis[maxn]; int N; void init(int n) { N=n; tol=0; memset(head,-1,sizeof(head)); } void AddEdge(int u,int v,int cap,int cost) { edges[tol].to=v; edges[tol].cap=cap; edges[tol].cost=cost; edges[tol].flow=0; edges[tol].next=head[u]; head[u]=tol++; edges[tol].to=u; edges[tol].cap=0; edges[tol].cost=-cost; edges[tol].flow=0; edges[tol].next=head[v]; head[v]=tol++; } bool spfa(int s,int t) { queue<int>q; for(int i=0;i<=N;i++){ dis[i]=inf; vis[i]=0; pre[i]=-1; } dis[s]=0; vis[s]=1; q.push(s); while(!q.empty()){ int u=q.front();q.pop(); vis[u]=0; for(int i=head[u];i!=-1;i=edges[i].next){ int v=edges[i].to; if(edges[i].cap>edges[i].flow&&dis[v]>dis[u]+edges[i].cost){ dis[v]=dis[u]+edges[i].cost; pre[v]=i; if(!vis[v]) {vis[v]=1;q.push(v);} } } } if(pre[t]==-1) return 0; return 1; } int MinCostFlow(int s,int t) { int flow=0,cost=0; while(spfa(s,t)){ int Min=inf; for(int i=pre[t];i!=-1;i=pre[edges[i^1].to]) Min=min(Min,edges[i].cap-edges[i].flow); for(int i=pre[t];i!=-1;i=pre[edges[i^1].to]){ edges[i].flow+=Min; edges[i^1].flow-=Min; cost+=edges[i].cost*Min; } flow+=Min; } return cost;//返回最小费用,flow存最大流 } /*********************************************************************/ int main() { int n,mp[605][605]; while(scanf("%d",&n)==1){ for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%d",&mp[i][j]); int s=0,t=n*n*2+1; init(n*n*2+2); for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ int id=(i-1)*n+j; if(id==1){ AddEdge(id,id+n*n,2,-mp[i][j]); AddEdge(s,id,2,0); } else if(id==n*n){ AddEdge(id,id+n*n,2,-mp[i][j]); AddEdge(id+n*n,t,2,0); } else AddEdge(id,id+n*n,1,-mp[i][j]); if(i<n) AddEdge(id+n*n,id+n,1,0); if(j<n) AddEdge(id+n*n,id+1,1,0); } } int ans=-(MinCostFlow(s,t)+mp[1][1]+mp[n][n]); printf("%d\n",ans); } return 0; }
给出代码供以后参考学习
标签:why pop 模型 java tar pos integer turn ted
原文地址:http://www.cnblogs.com/ruruozhenhao/p/7633035.html