NOJ 1548 hash+网络流
来源:互联网 发布:sql uniom 编辑:程序博客网 时间:2024/05/19 23:24
题目链接:http://cdn.ac.nbutoj.com/Problem/view.xhtml?id=1548
比赛链接:http://cdn.ac.nbutoj.com/Contest/view/id/68.xhtml
题意:
1、每种书在图书馆里有且仅有一本。
2、每个人阅读一本书需要一天。
3、当一个人阅读完一本书后会使社会幸福感增加1.
4、自然,当好孩子看完书后一大早就归还图书馆,不会影响第二天借书。
第一行给出n,m,K(1<=n,m<=50, 1<=K<=10)表示有n个人(编号从1-n),图书馆藏书m本(编号从1-m)。
下面n行第i行表示第i个人的借书情况,先给出两个整数 S, P(1<=S,P<=50)表示第i个人的借阅时间从第S天开始借阅(借阅时间是[S,S+K-1]),对P本书感兴趣,后面P个数字代表所感兴趣的书。
输出一个整数表示能增加的最大社会幸福感,若不能使社会更幸福就输出”If you do not leave me, I will by your side until the life end!”(不包括引号)
思路:
首先可以确定是网络流。
无责任民科表示:二分匹配较为简单,最大匹配数即是答案。(尚未找到ac代码,但我相信我民科定有O(n+m)复杂度的ac代码)
网络流:
人、书、时间三者互相约束,一天内一本书只能被一个人读。如果直接将三者hash 点数最大是n^3*k。
所以将其中两者hash出,最大点数可以降到n^2*k,而这个方法要注意在中间的因素要进行拆点,类似以下数据可以cha掉未拆点的代码:
3 2 2 1 2 1 21 1 11 1 13 3 21 2 2 32 2 2 32 2 2 34 1 21 1 11 1 12 1 12 1 13 2 21 1 12 2 1 23 2 1 2ans:3535
Note:
注意最后一天不是最迟到图书馆的lastday,而是lastday + (K-1)
建图:
最优的情况是每个人在K天内都阅读书,所以把人和K天hash出来,用一个点表示一个人一天的情况。
1、源点 与 人+K天 建边
2、人+K天 与 书+总天数(和K无关) 建边
3、书+总天数(和K无关) 与 汇点 建边
标程:
#include<stdio.h>#include<iostream>#include<string.h>#include<queue>#include<vector>using namespace std;#define N 100000#define M 1000000#define inf 536870912#define end Endinline int max(int a,int b){return a>b?a:b;}struct Edge{int from, to, cap, nex;}edge[M];int head[N], edgenum;void addedge(int u, int v, int cap){Edge E = { u, v, cap, head[u]};edge[ edgenum ] = E;head[u] = edgenum ++;Edge E2= { v, u, 0, head[v]};edge[ edgenum ] = E2;head[v] = edgenum ++;}int sign[N], s, t;bool BFS(int from, int to){memset(sign, -1, sizeof(sign));sign[from] = 0;queue<int>q;q.push(from);while( !q.empty() ){int u = q.front(); q.pop();for(int i = head[u]; i!=-1; i = edge[i].nex){int v = edge[i].to;if(sign[v]==-1 && edge[i].cap){sign[v] = sign[u] + 1, q.push(v);if(sign[to] != -1)return true;}}}return false;}int Stack[M], top, cur[M];int dinic(){int ans = 0, i;while( BFS(s, t) ){memcpy(cur, head, sizeof(head));int u = s;top = 0;while(1){if(u == t){int flow = inf, loc;for(i = 0; i < top; i++)if(flow > edge[ Stack[i] ].cap){flow = edge[Stack[i]].cap;loc = i;}for(i = 0; i < top; i++){edge[ Stack[i] ].cap -= flow;edge[Stack[i]^1].cap += flow;}ans += flow;top = loc;u = edge[Stack[top]].from;}for(i = cur[u]; i!=-1; cur[u] = i = edge[i].nex)if(edge[i].cap && (sign[u] + 1 == sign[ edge[i].to ]))break;if(cur[u] != -1){Stack[top++] = cur[u];u = edge[ cur[u] ].to;}else{if( top == 0 )break;sign[u] = -1;u = edge[ Stack[--top] ].from;}}}return ans;}int n, m, K;int from[101], lastday;vector<int>G[101];int peo_day(int peo, int day){return (peo-1)*K+day;}int book_day1(int book, int day){return (book-1)*lastday+day + n*K;}int book_day2(int book, int day){return (book-1)*lastday+day + lastday*m + n*K;}void init(){memset(head, -1, sizeof(head)); edgenum = 0;for(int i = 1; i <= n; i++)G[i].clear();s = 0;lastday = 0;}int main(){int i, j, k;while(~scanf("%d %d %d", &n, &m, &K)){init();for(i = 1; i <= n; i++){int booknum; scanf("%d %d",&from[i],&booknum);while(booknum--)scanf("%d",&j), G[i].push_back(j);lastday = max(lastday, from[i]);}lastday += K-1;t = 20000;for(i = 1; i <= n; i++)for(j = 1; j <= K; j++){addedge(s, peo_day(i,j), 1);//源点 - 人+K天for(int z = 0; z < G[i].size(); z++)addedge(peo_day(i,j), book_day1(G[i][z], j+from[i]-1), 1);}for(i = 1; i <= m; i++)for(j = 1; j <= lastday; j++)addedge(book_day1(i,j), book_day2(i,j), 1), addedge(book_day2(i,j), t, 1);printf("%d\n", dinic());}return 0;}
- NOJ 1548 hash+网络流
- NOJ 1013 MM网络
- NOJ 1075 社会关系网络
- NOJ 1075 社会关系网络 题解
- Noj
- 法师 南邮NOJ网络赛2083
- 送花 南邮NOJ网络选拔赛2084
- Football 南邮NOJ网络选拔赛2082
- NOJ 网络赛 D题 天神小学
- NOJ 网络赛 L题 送花
- NOJ 1075 社会关系网络 并查集
- 特技的幂 南邮NOJ网络选拔赛2075
- NOJ 网络赛 B题 pdf的旅游
- NOJ 网络赛 C题 特技的幂
- NOJ 1044 连通 OR 不连通 (离线并查集 + hash)
- hdu4277 USACO ORZ-----hash 长春网络赛
- NOJ 2015年陕西省程序设计竞赛网络预赛(正式赛)(随机数-水题)[Hobo]
- NOJ 2015年陕西省程序设计竞赛网络预赛(正式赛)(和谐的比赛-dp寻路)
- android VOIP
- Android中如何做到Service被关闭后又自动启动
- java接口
- JAVA 常用加密方法
- 微信服务器接口配置程序
- NOJ 1548 hash+网络流
- 菜鸟学习日记详细版--C和指针
- 自己通过位图实现了数字时钟
- 在windows系统下注册新服务
- Spring事务配置的五种方式
- 2014年学习计划
- Spring事务配置的五种方式
- 《剑指offer》第四章 解决面试题的思路 总结
- opensuse 安装ati显卡驱动