1737: 太空飞行计划问题 最大权闭合子图
1、建立两个超级点S,T。
2、对每个实验跟S链接一条容量为收入的边。
3、对每个一起跟T链接一条容量为花费的边。
4、对每个实验要用到的一起链接一条容量为无穷大的边。
链表
#include <iostream> #include <queue> #include <vector> #include <cstdio> #include <cstring> using namespace std; const int MAXN = 101,MAXM = MAXN*MAXN*2,INF = ~0U >> 1; struct Edge{ Edge *next,*op; int t,c; }*V[MAXN],*P[MAXN],ES[MAXM],*Stae[MAXN]; int N,M,S,T,EC,Ans,Maxflow; int Lv[MAXN],Stap[MAXN]; void Clear() { for(int i = 0;i < MAXN;++i) V[i] = NULL,ES[i].next = NULL,ES[i].op = NULL; EC = 0; Ans = 0; Maxflow = 0; } inline void addedge(int a,int b,int c) { ES[++EC].next = V[a];V[a] = ES+EC;V[a]->t = b;V[a]->c = c; ES[++EC].next = V[b];V[b] = ES+EC;V[b]->t = a;V[b]->c = 0; V[a]->op = V[b]; V[b]->op = V[a]; } bool Dinic_Lable() //构造层次图 { int head,tail,i,j; Stap[head=tail=0] = S; memset(Lv,-1,sizeof(Lv)); Lv[S] = 0; while(head<=tail){ i = Stap[head++]; for(Edge *e = V[i];e;e = e->next){ j = e->t; if(e->c&&Lv[j]==-1){ Lv[j] = Lv[i] + 1; if(j==T) return true; Stap[++tail] = j; } } } return false; } void Dinic_Augment() //增广 { int i,j,delta,Stop; for(i = S;i <= T;++i) P[i] = V[i]; Stap[Stop=1] = S; while(Stop){ i = Stap[Stop]; if(i != T){ for(;P[i];P[i] = P[i]->next) if(P[i]->c&&Lv[i]+1==Lv[j=P[i]->t]) break; if(P[i]){ Stap[++Stop] = j; Stae[Stop] = P[i]; } else Stop--,Lv[i] = -1; } else { delta = INF; for(i = Stop;i >= 2;--i) if(Stae[i]->c < delta) delta = Stae[i]->c; Maxflow += delta; for(i = Stop;i >= 2;--i){ Stae[i]->c -= delta; Stae[i]->op->c += delta; if(Stae[i]->c == 0) Stop = i-1; } } } } void Dinic() { while(Dinic_Lable()) Dinic_Augment(); } void init() { int i,a,c; S = 0; T = M+N+1; for(i = 1;i <= M;++i){ scanf("%d",&c); addedge(S,i,c); Ans += c; // for(;;){ // int sum = 0; // c = getchar(); // while(c == ' ')c = getchar(); // if(c=='\n') break; // while(c!=' '&&c!='\n'){ // sum *= 10; // sum += c - '0'; // c = getchar(); // } printf("sum == %d\n",sum); // addedge(i,sum+M,INF); // if(c=='\n') break; // } for (;;){ while((c=getchar())==' '); ungetc(c,stdin); if (c==10 || c==13) break; scanf("%d",&a); addedge(i,a+M,INF); } } for(i = 1;i <= N;++i){ scanf("%d",&c); addedge(i+M,T,c); } } void print() { for(int i = 1;i <= M;++i) if(Lv[i]!=-1) printf("%d ",i); putchar('\n'); for(int i = M+1;i <= M+N;++i) if(Lv[i]!=-1) printf("%d ",i-M); Ans -= Maxflow; printf("\n%d\n",Ans); } int main() { // freopen("Input.txt","r",stdin); while(~scanf("%d%d",&M,&N)){ Clear(); init(); Dinic(); print(); } return 0; }
容器实现
#include <iostream> #include <algorithm> #include <sstream> #include <vector> #include <queue> #include <cstdio> #include <cstring> using namespace std; const int MAXN = 1e3 + 5,INF = ~0U >> 2; struct Edge{ int from,to,cap,flow; Edge(int f,int t,int c,int _f) :from(f),to(t),cap(c),flow(_f){}; }; vector<Edge> edges; vector<int> G[MAXN]; int N,M,S,T; int d[MAXN],cur[MAXN]; bool vst[MAXN]; void Init() { for(int i = 0;i < MAXN;++i) G[i].clear(); edges.clear(); } inline void AddEdge(int from,int to,int cap) { edges.push_back(Edge(from,to,cap,0)); edges.push_back(Edge(to,from,0,0)); int sz = edges.size(); G[from].push_back(sz-2); G[to].push_back(sz-1); } bool BFS() { memset(vst,false,sizeof(vst)); queue<int> Q; Q.push(S); d[S] = 0; vst[S] = true; while(!Q.empty()){ int x = Q.front(); Q.pop(); for(int i = 0;i < (int)G[x].size();++i){ Edge& e = edges[G[x][i]]; if(!vst[e.to]&&e.cap>e.flow){ vst[e.to] = true; d[e.to] = d[x] + 1; Q.push(e.to); } } } return vst[T]; } int DFS(int u,int a) { if(u==T||a==0) return a; int f,flow = 0; for(int& i = cur[u];i < (int)G[u].size();++i){ Edge& e = edges[G[u][i]]; if(d[u]+1==d[e.to]&&(f=DFS(e.to,min(a,e.cap-e.flow)))>0){ e.flow += f; edges[G[u][i]^1].flow -= f; flow += f; a -= f; if(a==0)break; } } return flow; } int Maxflow() { int flow = 0; while(BFS()){ memset(cur,0,sizeof(cur)); flow += DFS(S,INF); } return flow; } void Solve() { int i,c,ans = 0; S = 0; T = M+N+1; for(i = 1;i <= M;++i){ scanf("%d",&c); AddEdge(S,i,c); ans += c; string str; getline(cin,str); istringstream ssin(str); while(ssin>>c) AddEdge(i,c+M,INF); } for(i = 1;i <= N;++i){ scanf("%d",&c); AddEdge(i+M,T,c); } int maxflow = Maxflow(); for(i = 1;i <= M;++i) if(vst[i]) printf("%d ",i); putchar('\n'); for(i = M+1;i <= M+N;++i) if(vst[i]) printf("%d ",i-M); printf("\n%d\n",ans-maxflow); } int main() { // freopen("Input.txt","r",stdin); while(~scanf("%d%d",&M,&N)){ Init(); Solve(); } return 0; }