CodeForces 103E

来源:互联网 发布:办公软件教学计划 编辑:程序博客网 时间:2024/06/07 19:28

给定n个结合
选出k个集合,并且这k个集合并后的大小也为k,求费用最小,
最大权闭合图

#include<cstdio>#include<iostream>#include<cstring>using namespace std;const int N=600+10;const int M=N*N;typedef __int64 LL;const int INF=1e9;struct Edge{    int v,next,cap;    Edge(){}    Edge(int v,int next ,int cap):v(v),next(next),cap(cap){}}e[M*2];int head[N],total;void init(){    memset(head,-1,sizeof(head));total=0;}void adde(int u,int v,int cap){    //printf("%d %d %d\n",u,v,cap);    e[total]=Edge(v,head[u],cap);head[u]=total++;    e[total]=Edge(u,head[v],0);head[v]=total++;}int num[N],cur[N],dis[N],pre[N],low[N];LL isap(int s,int t,int n){    memset(num,0,sizeof(num));num[0]=n;    memset(dis,0,sizeof(dis));    for(int i=0;i<n;i++)cur[i]=head[i];    int u=pre[s]=s;    low[s]=INF;    LL flow=0;    while(dis[s]<n){    loop:        for(int &i=cur[u];i!=-1;i=e[i].next)if(e[i].cap){            int v=e[i].v;            if(dis[v]+1!=dis[u])continue;            low[v]=min(low[u],e[i].cap);            pre[v]=u;            u=v;            if(u==t){                for(u=pre[u];v!=s;v=u,u=pre[u]){                    int id=cur[u];                    e[id].cap-=low[t];                    e[id^1].cap+=low[t];                }                flow+=low[t];                //printf("%d\n",low[t]);            }            goto loop;        }        int mm=n-1;        for(int i=head[u];i!=-1;i=e[i].next)if(e[i].cap){            int v=e[i].v;            if(dis[v]<mm){                cur[u]=i,mm=dis[v];            }        }        if(--num[dis[u]]==0)break;        num[dis[u]=mm+1]++;        u=pre[u];    }    return flow;}int aa[N];int main(){    #ifdef DouBi    freopen("in.cpp","r",stdin);    #endif // DouBi    int n;    while(scanf("%d",&n)!=EOF){        int s=0,t=n*2+1;        init();        for(int i=1;i<=n;i++){            int k;scanf("%d",&k);            while(k--){                int j;scanf("%d",&j);                adde(i,n+j,INF*2);            }        }        LL sum=0;        for(int i=1;i<=n;i++){            scanf("%d",&aa[i]);            adde(0,i,INF-aa[i]);            sum+=INF-aa[i];        }        for(int i=1;i<=n;i++){            adde(n+i,t,INF);        }        LL x=isap(s,t,2*n+2);        x=min((LL)0,-(sum-x));        printf("%I64d\n",x);    }    return 0;}
0 0
原创粉丝点击