题目链接:http://acm.nankai.edu.cn/p2122.html
题目大意:
中文题意,不解释。
题目思路:
最大权闭合图。
详解:http://blog.csdn.net/gotoac/article/details/8247023
由于要输出非选择的实验和仪器,喜欢用sap的兄弟最后从源点搜一遍,能遍历到的点就是选择了的。
代码:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
#define ll long long
#define ls rt<<1
#define rs ls|1
#define lson l,mid,ls
#define rson mid+1,r,rs
#define middle (l+r)>>1
#define eps (1e-8)
#define clr_all(x,c) memset(x,c,sizeof(x))
#define clr(x,c,n) memset(x,c,sizeof(x[0])*(n+1))
#define MOD 1000000009
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define _max(x,y) (((x)>(y))? (x):(y))
#define _min(x,y) (((x)<(y))? (x):(y))
#define _abs(x) ((x)<0? (-(x)):(x))
#define getmin(x,y) (x= ((x)<0 || (y)<(x))? (y):(x))
#define getmax(x,y) (x= ((y)>(x))? (y):(x))
template <class T> void _swap(T &x,T &y){T t=x;x=y;y=t;}
int TS,cas=1;
const int M=500+5;
int n,m;
struct sap{
typedef int type;
struct edge{
int from,to;
type flow;
edge(int u=0,int v=0,type f=0){from=u,to=v,flow=f;}
};
vector<edge>edg; //边表
vector<int>g[M]; //邻接表
int n,m; //顶点数,边数
int cur[M],dis[M];//当前弧,距离标号
int pre[M],gap[M];//上一条弧,间隙优化
void init(int _n){
n=_n,edg.clear();
for(int i=0;i<n;i++) g[i].clear();
}
void insert(int u,int v,type f){
edg.push_back(edge(u,v,f)),edg.push_back(edge(v,u,0));
m=edg.size();
g[u].push_back(m-2),g[v].push_back(m-1);
}
type maxFlow(int s,int t){
type res=0,a;
clr(cur,0,n),clr(gap,0,n),clr(dis,0,n);
gap[0]=n;
for(int u=s;dis[s]<n;){
if(u==t){
for(a=-1;u!=s;u=edg[pre[u]].from)
getmin(a,edg[pre[u]].flow);
for(u=t;u!=s;u=edg[pre[u]].from)
edg[pre[u]].flow-=a,edg[pre[u]^1].flow+=a;
res+=a;
}
bool ok=0;
for(int& i=cur[u];i<g[u].size();i++){
edge& e=edg[g[u][i]];
if(dis[u]==dis[e.to]+1 && e.flow>0){
pre[e.to]=g[u][i],u=e.to,ok=1;
break;
}
}
if(!ok){
int mindis=n-1;
for(int i=0;i<g[u].size();i++){
edge& e=edg[g[u][i]];
if(mindis>dis[e.to] && e.flow>0)
mindis=dis[e.to],cur[u]=i;
}
if(--gap[dis[u]]==0) break;
gap[dis[u]=mindis+1]++;
if(u!=s) u=edg[pre[u]].from;
}
}
return res;
}
int q[M],head,tail;
void getS(int s){
clr(dis,-1,n);
dis[s]=0;
for(q[head=tail=0]=s;head<=tail;){
int u=q[head++];
for(int i=0;i<g[u].size();i++){
edge& e=edg[g[u][i]];
if(dis[e.to]==-1 && e.flow>0){
dis[e.to]=0;
q[++tail]=e.to;
}
}
}
}
}p;
void run(){
int i,j;
p.init(n+m+2);
int tot=0;
for(i=1;i<=m;i++){
scanf("%d",&j);
tot+=j;
p.insert(0,n+i,j);
while(scanf("%d",&j)){
char c=getchar();
p.insert(n+i,j,INF);
if(c=='\n') break;
}
}
for(i=1;i<=n;i++){
scanf("%d",&j);
p.insert(i,n+m+1,j);
}
int ans=tot-p.maxFlow(0,n+m+1);
p.getS(0);
bool flag;
for(flag=0,i=n+1;i<=n+m;i++){
if(p.dis[i]==-1) continue;
if(flag) printf(" %d",i-n);
else printf("%d",i-n),flag=1;
}puts("");
for(flag=0,i=1;i<=n;i++){
if(p.dis[i]==-1) continue;
if(flag) printf(" %d",i);
else printf("%d",i),flag=1;
}puts("");
printf("%d\n",ans);
}
void preSof(){
}
int main(){
//freopen("input.txt","r",stdin);
//freopen("output.txt","w",stdout);
preSof();
//run();
while(scanf("%d%d",&m,&n)!=EOF) run();
//for(scanf("%d",&TS);cas<=TS;cas++) run();
return 0;
}