链接:https://www.oj.swust.edu.cn/oj/problem/show/1737
分析:把实验和仪器都看做点,点权为盈利(仪器的盈利为负),从实验到所需仪器连一条边,求图的最大权闭合图。
最大权闭合图求法:增加源汇点s、t,对于每个点,设权重为w,若w>0,从s向该点连一条边,容量为w,若w<0,从该点向t连一条边,容量为-w,再把原有的边全部容量改为无穷大,求一下该图的最小割即为最大权,割完和s所在集合就是最大权闭合图,也就是需要做的实验和需要的仪器。
1 #include<iostream> 2 #include<vector> 3 #include<queue> 4 #include<stack> 5 #include<cstdio> 6 #include<cstring> 7 using namespace std; 8 const int maxn=1e3+5,INF=1e9; 9 int m,n; 10 struct Edge{ 11 int from,to,cap,flow; 12 Edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f){} 13 }; 14 struct ISAP{ 15 int n,s,t; 16 vector<Edge> edges; 17 vector<int> G[maxn]; 18 bool vis[maxn]; 19 int d[maxn]; 20 int cur[maxn]; 21 int p[maxn]; 22 int num[maxn]; 23 24 void init(int n){ 25 this->n=n; 26 edges.clear(); 27 for(int i=0;i<n;i++)G[i].clear(); 28 } 29 30 void AddEdge(int from,int to,int cap){ 31 edges.push_back(Edge(from,to,cap,0)); 32 edges.push_back(Edge(to,from,0,0)); 33 G[from].push_back(edges.size()-2); 34 G[to].push_back(edges.size()-1); 35 } 36 37 void BFS(){ 38 memset(vis,0,sizeof(vis)); 39 queue<int> Q; 40 Q.push(t); 41 d[t]=0; 42 vis[t]=1; 43 while(!Q.empty()){ 44 int x=Q.front();Q.pop(); 45 for(int i=0;i<G[x].size();i++){ 46 Edge &e=edges[G[x][i]^1]; 47 if(e.flow==e.cap)continue; 48 if(!vis[e.from]){ 49 vis[e.from]=1; 50 d[e.from]=d[x]+1; 51 Q.push(e.from); 52 } 53 } 54 } 55 } 56 57 int Augment(){ 58 int x=t,a=INF; 59 while(x!=s){ 60 Edge &e=edges[p[x]]; 61 a=min(a,e.cap-e.flow); 62 x=edges[p[x]].from; 63 } 64 x=t; 65 while(x!=s){ 66 edges[p[x]].flow+=a; 67 edges[p[x]^1].flow-=a; 68 x=edges[p[x]].from; 69 } 70 return a; 71 } 72 73 int Maxflow(int s,int t){ 74 this->s=s;this->t=t; 75 int flow=0; 76 BFS(); 77 memset(num,0,sizeof(num)); 78 for(int i=0;i<n;i++)num[d[i]]++; 79 int x=s; 80 memset(cur,0,sizeof(cur)); 81 while(d[s]<n){ 82 if(x==t){ 83 flow+=Augment(); 84 x=s; 85 } 86 int ok=0; 87 for(int i=cur[x];i<G[x].size();i++){ 88 Edge &e=edges[G[x][i]]; 89 if(e.cap>e.flow&&d[x]==d[e.to]+1){ 90 ok=1; 91 p[e.to]=G[x][i]; 92 cur[x]=i; 93 x=e.to; 94 break; 95 } 96 } 97 if(!ok){ 98 int m=n-1; 99 for(int i=0;i<G[x].size();i++){ 100 Edge &e=edges[G[x][i]]; 101 if(e.cap>e.flow)m=min(m,d[e.to]); 102 } 103 if(--num[d[x]]==0)break; 104 num[d[x]=m+1]++; 105 cur[x]=0; 106 if(x!=s)x=edges[p[x]].from; 107 } 108 } 109 return flow; 110 } 111 }isap; 112 113 int main(){ 114 // freopen("e:\in.txt","r",stdin); 115 scanf("%d%d",&m,&n); 116 char c; 117 int v,ans=0; 118 isap.init(n+m+2); 119 for(int i=n+1;i<=n+m;i++){ 120 scanf("%d",&v); 121 ans+=v; 122 isap.AddEdge(0,i,v); 123 c=getchar(); 124 while(c==' '){ 125 scanf("%d",&v); 126 c=getchar(); 127 isap.AddEdge(i,v,INF); 128 } 129 } 130 for(int i=1;i<=n;i++){ 131 scanf("%d",&v); 132 isap.AddEdge(i,n+m+1,v); 133 } 134 ans-=isap.Maxflow(0,n+m+1); 135 isap.BFS(); 136 for(int i=n+1;i<=n+m;i++){ 137 if(!isap.vis[i]){ 138 printf("%d ",i-n); 139 } 140 } 141 142 printf(" "); 143 for(int i=1;i<=n;i++){ 144 if(!isap.vis[i]){ 145 printf("%d ",i); 146 } 147 } 148 printf(" "); 149 printf("%d ",ans); 150 return 0; 151 }