hdu3251 最小割
Posted claireyuancy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu3251 最小割相关的知识,希望对你有一定的参考价值。
题意:
给n个城市,m条有向边。每条边有权值,如今有些城市能够选择得到。可选的城市有一个价值。可是要满足从1到达不了这些城市,为了满足要求能够去掉一些边,须要花费边的权值,问终于得到的最大价值是多少,并给出方案。
最小割 = 最大流
建图非常easy。源点就是1,设置汇点T。
按图中的有向边关系连边。
对于全部的可选择的城市u,连一条u->T的容量为w的边。
跑一遍最大流。即为最小割。
ans = sum - 最小割。
写出方案。就是走一遍bfs。看 哪些满流边(而且边的汇不是T,这是由于这种边是所选的城市扩展的边),打出来就好。
代码:
#include<iostream> #include<cstdio> #include<vector> #include<queue> #include<cmath> #include<cstring> using namespace std; const int N = 1000 + 10 ; const int inf = 1000000000; typedef long long ll; struct Edge { int from,to,cap,flow; }; int n,m,s,t,num,f; int w[N],use[N]; int vis[2*N],cur[2*N]; vector<int> G[2*N]; vector<Edge> edges; queue<int> cut; void init() { edges.clear(); for(int i=1;i<=n;i++) G[i].clear(); memset(vis,0,sizeof(vis)); } int add(int u,int v,int c) { edges.push_back((Edge){u,v,c,0}); edges.push_back((Edge){v,u,0,0}); num = edges.size(); G[u].push_back(num-2); G[v].push_back(num-1); } int bfs() { int front; memset(vis,0,sizeof(vis)); vis[s] = 1; queue<int> q; q.push(s); while(!q.empty()){ front = q.front(); q.pop(); for(int i=0;i<G[front].size();i++) { Edge& e = edges[G[front][i]]; if(!vis[e.to] && e.cap > e.flow) { q.push(e.to); vis[e.to] = vis[front]+1; } } } return vis[t]; } int dfs(int x,int a) { if(x==t || a==0) return a; int f=0,flow=0; for(int i=0;i<G[x].size();i++){ Edge& e = edges[G[x][i]]; if(vis[e.to]==vis[x]+1 && (f=dfs(e.to,min(a,e.cap-e.flow)))>0 ) { flow += f; e.flow += f; a -= f; edges[G[x][i]^1].flow -= f; if(a==0) break; } } return flow; } int dinic() { int flow = 0; while(bfs()) { memset(cur,0,sizeof(cur)); flow += dfs(s,inf); } return flow; } void find_cut() { while(!cut.empty()) cut.pop(); memset(vis,0,sizeof(vis)); vis[1] = 1; queue<int> q; q.push(1); int front; while(!q.empty()){ front = q.front(); q.pop(); for(int i=0;i<G[front].size();i++){ Edge& e = edges[G[front][i]]; if(!vis[e.to] && e.cap > e.flow){ vis[e.to] = 1; q.push(e.to); } } } for(int i=1;i<=n;i++){ if(vis[i]) for(int j=0;j<G[i].size();j++){ Edge& e = edges[G[i][j]]; if(G[i][j]&1) continue; if(e.to!=t && !vis[e.to]) cut.push(G[i][j]/2+1); } } return ; } void print_cut() { int len = cut.size(); int ro; cout<<len<<" "; for(int i=1;i<len;i++){ ro = cut.front(); cut.pop(); printf("%d ",ro); } ro = cut.front(); cut.pop(); printf("%d\n",ro); } int main() { int T,cas=0; scanf("%d",&T); while(T--){ ll sum = 0; scanf("%d%d%d",&n,&m,&f); init(); s = 1; t = n+1; for(int i=1;i<=m;i++){ int u,v,w; scanf("%d%d%d",&u,&v,&w); add(u,v,w); } for(int i=1;i<=f;i++){ int u,w; scanf("%d%d",&u,&w); add(u,t,w); sum += w; } ll ans = dinic(); find_cut(); printf("Case %d: %lld\n",++cas,sum-ans); print_cut(); } return 0; }
以上是关于hdu3251 最小割的主要内容,如果未能解决你的问题,请参考以下文章