Sset

神犇考题第三题:

设 S ={x|x∈Z,1≤x≤n}给定 N 个 S 的子集 Si,每个集合有一个权值 Wi。这 N 个集合满足其中任意 K 个集合的并集中至少有 K 个元素。请从中选取若干个集合(可以不选),使得其并集的元素个数恰等于选取的集合数,且这些集合的权值和最小。

考试的时候觉得这个题相比另外两个挺可写的,于是就使劲想,想出了最大权闭合图,想出了每个集合代表一个数字,可就是没想到把这两个联系起来,无奈,最后还是在包含关系的时候出搞错了,果然我还是太弱了,构造能力捉急。

首先有一个非常有用的条件,就是任意k个集合的并集中至少有k个元素,那么,如果有一个合法的方案,那么一定可以用一个单独的元素来代表这一个集合。

我们考虑拿到一个集合权值的代价,就是要将这个集合的所有元素都拿到(k个集合,k个元素),怎么办呢?我们只要找到所有元素表示的集合,把它们都拿到就行了。但与此同时我们拿到的集合可能会额外增加许多元素,那么把这些元素代表的集合也拿到,直到不会产生新的元素为止,这就是一个闭合图了。

于是把权值取反,跑一遍最大权闭合图就行了。

这个题精髓是条件的转化与模型的构造。

sset
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cmath>
  5 #include<cstring>
  6 #define maxn 1000
  7 #define maxm 120000
  8 #define inf 2147483647
  9 using namespace std;
 10 struct et
 11 {
 12     int s,t,val,next;
 13 }e[maxm];
 14 int dis[maxn],gap[maxn],fir[maxn],last[maxn],g[maxn],s[maxm],t[maxm],next[maxm],mat[maxn],sign[maxn];
 15 int a[maxn][maxn];
 16 bool v[maxn];
 17 int n,m,tot,st,ed,num,top;
 18 
 19 bool match(int x)
 20 {
 21     for (int j=fir[x];j;j=next[j])
 22     {
 23         int k=t[j];
 24         if (!v[k])
 25         {
 26             v[k]=1;
 27             if (mat[k]==0||match(mat[k]))
 28             {
 29                 mat[k]=x;
 30                 return 1;
 31             }
 32         }
 33     }
 34     return 0;
 35 }
 36 
 37 int dfs(int now,int flow)
 38 {
 39     if (now==ed) return flow;
 40     int sap=0;
 41     for (int j=last[now];j;j=e[j].next)
 42     {
 43         int k=e[j].t;
 44         if (e[j].val&&dis[now]==dis[k]+1)
 45         {
 46             last[now]=j;
 47             int tmp=dfs(k,min(e[j].val,flow-sap));
 48             e[j].val-=tmp;
 49             e[j^1].val+=tmp;
 50             sap+=tmp;
 51             if (sap==flow) return sap;
 52         }
 53     }
 54     if (dis[st]>=num) return sap;
 55     if (!(--gap[dis[now]])) dis[st]=num;
 56     ++gap[++dis[now]];
 57     last[now]=fir[now];
 58     return sap;
 59 }
 60 
 61 void add(int x,int y,int z)
 62 {
 63     e[++tot].s=x; e[tot].t=y; e[tot].val=z; e[tot].next=fir[x]; fir[x]=tot;
 64     e[++tot].s=y; e[tot].t=x; e[tot].val=0; e[tot].next=fir[y]; fir[y]=tot;
 65 }
 66 
 67 int main()
 68 {
 69     //freopen("sset.in","r",stdin);
 70     //freopen("sset.out","w",stdout);
 71     scanf("%d",&n);
 72     //构造二分图
 73     tot=0;
 74     for (int i=1;i<=n;i++)
 75     {
 76         scanf("%d",&g[i]);
 77         for (int j=1;j<=g[i];j++)
 78         {
 79             scanf("%d",&a[i][j]);
 80             s[++tot]=i; t[tot]=a[i][j]; next[tot]=fir[i]; fir[i]=tot;
 81         }
 82     }
 83     //跑完美匹配
 84     for (int i=1;i<=n;i++)
 85     {
 86         memset(v,0,sizeof(v));
 87         match(i);
 88     }
 89     for (int i=1;i<=n;i++) sign[mat[i]]=i;
 90     memset(fir,0,sizeof(fir));
 91     //构造最大权闭合图
 92     st=0; ed=n+1; num=n+2; tot=1;
 93     for (int i=1;i<=n;i++)
 94         for (int j=1;j<=g[i];j++)
 95             if (a[i][j]!=sign[i]) add(i,mat[a[i][j]],inf);
 96     int z,sum=0;
 97     for (int i=1;i<=n;i++)
 98     {
 99         scanf("%d",&z);
100         z=-z;
101         if (z>0) add(st,i,z),sum+=z;else add(i,ed,-z);
102     }
103     //跑网络流
104     memset(dis,0,sizeof(dis));
105     memset(gap,0,sizeof(gap));
106     gap[0]=num;
107     for (int i=st;i<=ed;i++) last[i]=fir[i];
108     int ans=0;
109     while (dis[st]<num) ans+=dfs(st,inf);
110     if (sum-ans>0) printf("%d\n",-(sum-ans));
111     else printf("%d\n",0);
112     return 0;
113 }

 

转载于:https://www.cnblogs.com/zig-zag/archive/2013/05/04/3059600.html

技术选型 【后端】:Java 【框架】:springboot 【前端】:vue 【JDK版本】:JDK1.8 【服务器】:tomcat7+ 【数据库】:mysql 5.7+ 项目包含前后台完整源码。 项目都经过严格调试,确保可以运行! 具体项目介绍可查看博主文章或私聊获取 助力学习实践,提升编程技能,快来获取这份宝贵的资源吧! 在当今快速发展的信息技术领域,技术选型是决定一个项目成功与否的重要因素之一。基于以下的技术栈,我们为您带来了一份完善且经过实践验证的项目资源,让您在学习和提升编程技能的道路上事半功倍。以下是该项目的技术选型和其组件的详细介绍。 在后端技术方面,我们选择了Java作为编程语言。Java以其稳健性、跨平台性和丰富的库支持,在企业级应用中处于领导地位。项目采用了流行的Spring Boot框架,这个框架以简化Java企业级开发而闻名。Spring Boot提供了简洁的配置方式、内置的嵌入式服务器支持以及强大的生态系统,使开发者能够更高效地构建和部署应用。 前端技术方面,我们使用了Vue.js,这是一个用于构建用户界面的渐进式JavaScript框架。Vue以其易上手、灵活和性能出色而受到开发者的青睐,它的组件化开发思想也有助于提高代码的复用性和可维护性。 项目的编译和运行环境选择了JDK 1.8。尽管Java已经推出了更新的版本,但JDK 1.8依旧是一种成熟且稳定的选择,广泛应用于各类项目中,确保了兼容性和稳定性。 在服务器方面,本项目部署在Tomcat 7+之上。Tomcat是Apache软件基金会下的一个开源Servlet容器,也是应用最为广泛的Java Web服务器之一。其稳定性和可靠的性能表现为Java Web应用提供了坚实的支持。 数据库方面,我们采用了MySQL 5.7+。MySQL是一种高效、可靠且使用广泛的关系型数据库管理系统,5.7版本在性能和功能上都有显著的提升。 值得一提的是,该项目包含了前后台的完整源码,并经过严格调试,确保可以顺利运行。通过项目的学习和实践,您将能更好地掌握从后端到前端的完整开发流程,提升自己的编程技能。欢迎参考博主的详细文章或私信获取更多信息,利用这一宝贵资源来推进您的技术成长之路!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值