建模方式:
1 :构造一个图 N ,顶点有 Ii(1<=i<=n) , Ej(1<=j<=m) 以及一个源 S 和汇 T
2
:从源点出发,向每个实验 Ei
引出一条容量为 Pi
的有向边
3
:从每个仪器 Ij
出发,向汇点引出一条容量为 costi 的有向边
4
:每个实验分别向所需的仪器引出一条容量为 +∞
的有向边
这样用总收入减去最大流即为答案,统计方式可以采用删去一边然后暴力跑网络流判断。
By:大奕哥
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=1005,inf=1e9; 4 int head[N],cnt=-1,p[N],cost[N],v[N],m,n,ulen,s,t; 5 char c[N]; 6 vector<int>ex[N]; 7 queue<int>q; 8 struct node{ 9 int to,nex,w; 10 }e[N<<1],a[N<<1]; 11 void add(int x,int y,int w) 12 { 13 e[++cnt].to=y;e[cnt].nex=head[x];head[x]=cnt;e[cnt].w=w; 14 e[++cnt].to=x;e[cnt].nex=head[y];head[y]=cnt;e[cnt].w=0; 15 } 16 bool bfs(int x,int y) 17 { 18 memset(v,-1,sizeof(v)); 19 v[x]=0;q.push(x); 20 while(!q.empty()) 21 { 22 int x=q.front();q.pop(); 23 for(int i=head[x];i!=-1;i=e[i].nex) 24 { 25 int y=e[i].to; 26 if(!e[i].w||v[y]!=-1)continue; 27 v[y]=v[x]+1; 28 q.push(y); 29 } 30 } 31 return v[y]!=-1; 32 } 33 int dfs(int x,int w,int yy) 34 { 35 if(!w||x==yy)return w; 36 int s=0; 37 for(int i=head[x];i!=-1;i=e[i].nex) 38 { 39 int y=e[i].to; 40 if(v[y]!=v[x]+1||!e[i].w)continue; 41 int flow=dfs(y,min(w-s,e[i].w),yy); 42 s+=flow;e[i].w-=flow;e[i^1].w+=flow; 43 if(!flow)v[y]=-1; 44 if(s==w)return s; 45 } 46 return s; 47 } 48 int dinic(int x,int y) 49 { 50 int ans=0; 51 while(bfs(x,y)){ 52 ans+=dfs(x,inf,y); 53 } 54 return ans; 55 } 56 void copy() 57 { 58 for(int i=0;i<=cnt;++i)a[i].w=e[i].w; 59 } 60 void copy2() 61 { 62 for(int i=0;i<=cnt;++i)e[i].w=a[i].w; 63 } 64 bool use1[N],use2[N]; 65 int main() 66 { 67 scanf("%d%d",&m,&n); 68 int sum=0,ans,num; 69 memset(head,-1,sizeof(head)); 70 for(int i=1;i<=m;++i) 71 { 72 scanf("%d",&p[i]); 73 sum+=p[i]; 74 memset(c,0,sizeof(c)); 75 cin.getline(c,10000); 76 ulen=0; 77 while(sscanf(c+ulen,"%d",&num)==1) 78 { 79 ex[i].push_back(num); 80 if(!num)ulen++; 81 else while(num) 82 { 83 num/=10; 84 ulen++; 85 } 86 ulen++; 87 } 88 } 89 for(int i=1;i<=n;++i)scanf("%d",&cost[i]); 90 s=0,t=1000; 91 for(int i=1;i<=m;++i) 92 add(s,i,p[i]); 93 for(int i=1;i<=n;++i) 94 add(i+m,t,cost[i]); 95 for(int i=1;i<=m;++i) 96 { 97 for(int j=0;j<ex[i].size();++j) 98 add(i,ex[i][j]+m,inf); 99 } 100 copy(); 101 ans=dinic(s,t); 102 for(int i=head[t];i!=-1;i=e[i].nex) 103 { 104 copy2(); 105 int tmp=e[i^1].w; 106 e[i^1].w=0; 107 int pre=dinic(s,t); 108 if(ans-pre==tmp)use1[e[i].to-m]=1; 109 e[i^1].w=tmp; 110 } 111 for(int i=1;i<=m;++i) 112 { 113 use2[i]=1; 114 for(int j=0;j<ex[i].size();++j) 115 if(!use1[ex[i][j]]) 116 { 117 use2[i]=0;break; 118 } 119 } 120 for(int i=1;i<=m;++i) 121 if(use2[i])printf("%d ",i); 122 puts(""); 123 for(int i=1;i<=n;++i) 124 if(use1[i])printf("%d ",i); 125 puts(""); 126 printf("%d\n",sum-ans); 127 return 0; 128 }