CDOJ 1195 Find the Treasure

    技术2022-05-13  0

    还是经典的最小割模型

    源点与每把钥匙连边,容量为钥匙的代价,每个宝物与汇点连边,容量为宝物的价值

    然后每把钥匙与需要用它去开启的宝物连边,容量为无穷

     

    获利为Sum(宝物的价值)-(需要的钥匙的代价+开启的宝物的价值,即最小割)

     

    最后,与源点相连的切是割边的那些钥匙是必须的钥匙,注意的是,容量为0不一定为割边,但割边的容量一定为0

    例如这组数据

    1

    3 3

    2 4 3

    1 5 6

    0

    2 1 2

    1 3

     

    答案为

    4

    1 3

     

    代码:

    /* 5 4 4 7 4 2 7 7 9 0 0 1 2 1 4 1 3 1 1 3 3 2 4 5 3 6 8 1 1 2 1 2 3 1 2 3 3 3 1 2 3 4 5 5 1 1 2 1 2 1 3 3 3 1 2 3 4 5 5 1 1 2 1 2 1 1 3 3 2 4 3 1 5 6 0 2 1 2 1 3 */ #include<iostream> #include<cstdio> #include<memory.h> #include<algorithm> using namespace std; const int inf=1<<30; const int MAX=450; struct node { int v,c,next; }g[MAX*100]; int adj[MAX],cur[MAX],dis[MAX],num[MAX],pre[MAX],res[MAX],vis[MAX]; int n,m,s,t,vn,e,cnt; void add(int u,int v,int c) { g[e].v=v; g[e].c=c; g[e].next=adj[u]; adj[u]=e++; g[e].v=u; g[e].c=0; g[e].next=adj[v]; adj[v]=e++; } int sap() { int flow=0,u,v,tmp,aug=inf+1,i; bool flag; //memset(pre,0,sizeof(pre)); for(i=0;i<=vn;i++) { dis[i]=num[i]=0; cur[i]=adj[i]; } u=pre[s]=s; num[0]=vn; while(dis[s]<vn) { flag=false; for(i=cur[u];i!=-1;i=g[i].next) { v=g[i].v; if(g[i].c&&dis[u]==dis[v]+1) { flag=true; cur[u]=i; pre[v]=u; aug=aug<g[i].c?aug:g[i].c; u=v; if(u==t) { flow+=aug; while(u!=s) { u=pre[u]; g[cur[u]].c-=aug; g[cur[u]^1].c+=aug; } aug=inf+1; } break; } } if(flag) continue; if(--num[dis[u]]==0) break; tmp=vn; for(i=adj[u];i!=-1;i=g[i].next) { v=g[i].v; if(g[i].c&&dis[v]<tmp) { tmp=dis[v]; cur[u]=i; } } dis[u]=tmp+1; num[dis[u]]++; u=pre[u]; } return flow; } void dfs(int u) { vis[u]=1; for(int i=adj[u];i!=-1;i=g[i].next) { if(!vis[g[i].v]&&g[i].c) dfs(g[i].v); } } int main() { int i,j,k,l,T,sum; scanf("%d",&T); while(T--) { scanf("%d %d",&n,&m); sum=0; memset(adj,-1,sizeof(adj)); e=0; s=0; t=m+n+1; vn=t+1; //cout<<n<<m<<endl; for(i=1;i<=n;i++) { scanf("%d",&j); add(s,i,j); } for(i=1;i<=m;i++) { scanf("%d",&j); sum+=j; add(n+i,t,j); } //cout<<"yes"<<endl; for(i=1;i<=m;i++) { scanf("%d",&k); //cout<<k<<endl; for(l=1;l<=k;l++) { scanf("%d",&j); add(j,i+n,inf); } } //cout<<"yes"<<endl; //cout<<sap()<<endl; printf("%d/n",sum-sap()); cnt=0; memset(vis,0,sizeof(vis)); dfs(s); for(i=adj[s];i!=-1;i=g[i].next) { if(!vis[g[i].v]) { //cout<<g[i].v<<endl; res[cnt++]=g[i].v; } } /*for(j=n+1;j<=n+m;j++) { for(i=adj[j];i!=-1;i=g[i].next) { if(g[i].c&&g[i].v==t) { res[cnt++]=j; cout<<j<<endl; } } } //cout<<cnt<<endl; int cnt2=0; for(j=0;j<cnt;j++) { for(i=adj[res[j]];i!=-1;i=g[i].next) { if(g[i].v<=n) { if(!vis[g[i].v]) cnt2++; vis[g[i].v]=1; } } } printf("%d",cnt2);*/ printf("%d",cnt); /*for(i=1;i<=n;i++) { if(vis[i]) printf(" %d",i); }*/ for(i=cnt-1;i>=0;i--) printf(" %d",res[i]); printf("/n"); } return 0; } 


    最新回复(0)