tsinsen A1220. 复杂的大门(陈许旻)
2016-02-26 20:30
176 查看
A1220. 复杂的大门(陈许旻)
时间限制:1.0s 内存限制:512.0MB
总提交次数:132
AC次数:74 平均分:67.84
试题来源
2011中国国家集训队命题答辩
问题描述
你去找某bm玩,到了门口才发现要打开他家的大门不是一件容易的事……
他家的大门外有n个站台,用1到n的正整数编号。你需要对每个站台访问一定次数以后大门才能开启。站台之间有m个单向的传送门,通过传送门到达另一个站台不需要花费任何代价。而如果不通过传送门,你就需要乘坐公共汽车,并花费1单位的钱。值得庆幸的是,任意两个站台之间都有公共汽车直达。
现在给你每个站台必须访问的次数Fi,对于站台i,你必须恰好访问Fi次(不能超过)。
我们用u、v、w三个参数描述一个传送门,表示从站台u到站台v有一个最多可以使用w次的传送门(不一定要使用w次)。值得注意的是,对于任意一对传送门(u1,v1)和(u2,v2),如果有u1<u2,则有v1≤v2;如果有v1<v2,则有u1≤u2;且u1=u2和v1=v2不同时成立。
你可以从任意的站台开始,从任意的站台结束。出发去开始的站台需要花费1单位的钱。你需要求出打开大门最少需要花费多少单位的钱。
输入格式
第一行包含两个正整数n、m,意义见题目描述。
第二行包含n个正整数,第i个数表示Fi。
接下来有m行,每行有三个正整数u、v、w,表示从u到v有一个可以使用w次的传送门。
输出格式
输出一行一个整数,表示打开大门最少花费的钱数。
样例输入
4 3
5 5 5 5
1 2 1
3 2 1
3 4 1
样例输出
17
数据规模及约定
有20%的数据满足n≤10,m≤50;对于所有的w、Fi,满足1≤w,Fi≤10。有50%的数据满足n≤1000,m≤10000。100%的数据满足1≤n≤10000,1≤m≤100000;对于所有的u、v,满足1≤u,v≤n,u≠v;对于所有的w、Fi,满足1≤w,Fi≤50000。
以上的每类数据中都存在50%的数据满足对于所有的w、Fi,有w=Fi=1。
时限1s
题解:此题是一道网络流的题目。输出打开大门最少花费的钱数实际上就是求总的经过的数目-最大使用传送门的次数,而最多使用传送门的次数可以用最大流来求解。
首先拆点,把每个点拆成起点和终点,然后从源点向所有的起点连边,权值为该点所需要的经过次数,然后从终点向汇点连边,权值为该点所需要的经过次数,然后处理传送门的信息,传送门的起点向终点连边,权值为传送门最大使用的次数。这样就可以跑最大流啦。因为是二分图,所有果断选择dinic。
时间限制:1.0s 内存限制:512.0MB
总提交次数:132
AC次数:74 平均分:67.84
试题来源
2011中国国家集训队命题答辩
问题描述
你去找某bm玩,到了门口才发现要打开他家的大门不是一件容易的事……
他家的大门外有n个站台,用1到n的正整数编号。你需要对每个站台访问一定次数以后大门才能开启。站台之间有m个单向的传送门,通过传送门到达另一个站台不需要花费任何代价。而如果不通过传送门,你就需要乘坐公共汽车,并花费1单位的钱。值得庆幸的是,任意两个站台之间都有公共汽车直达。
现在给你每个站台必须访问的次数Fi,对于站台i,你必须恰好访问Fi次(不能超过)。
我们用u、v、w三个参数描述一个传送门,表示从站台u到站台v有一个最多可以使用w次的传送门(不一定要使用w次)。值得注意的是,对于任意一对传送门(u1,v1)和(u2,v2),如果有u1<u2,则有v1≤v2;如果有v1<v2,则有u1≤u2;且u1=u2和v1=v2不同时成立。
你可以从任意的站台开始,从任意的站台结束。出发去开始的站台需要花费1单位的钱。你需要求出打开大门最少需要花费多少单位的钱。
输入格式
第一行包含两个正整数n、m,意义见题目描述。
第二行包含n个正整数,第i个数表示Fi。
接下来有m行,每行有三个正整数u、v、w,表示从u到v有一个可以使用w次的传送门。
输出格式
输出一行一个整数,表示打开大门最少花费的钱数。
样例输入
4 3
5 5 5 5
1 2 1
3 2 1
3 4 1
样例输出
17
数据规模及约定
有20%的数据满足n≤10,m≤50;对于所有的w、Fi,满足1≤w,Fi≤10。有50%的数据满足n≤1000,m≤10000。100%的数据满足1≤n≤10000,1≤m≤100000;对于所有的u、v,满足1≤u,v≤n,u≠v;对于所有的w、Fi,满足1≤w,Fi≤50000。
以上的每类数据中都存在50%的数据满足对于所有的w、Fi,有w=Fi=1。
时限1s
题解:此题是一道网络流的题目。输出打开大门最少花费的钱数实际上就是求总的经过的数目-最大使用传送门的次数,而最多使用传送门的次数可以用最大流来求解。
首先拆点,把每个点拆成起点和终点,然后从源点向所有的起点连边,权值为该点所需要的经过次数,然后从终点向汇点连边,权值为该点所需要的经过次数,然后处理传送门的信息,传送门的起点向终点连边,权值为传送门最大使用的次数。这样就可以跑最大流啦。因为是二分图,所有果断选择dinic。
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<queue> using namespace std; int n,m,i,j,f[10003],sum=0; int tot,next[400003],point[30000],v[400003],remain[400003]; int deep[30000],cur[30000]; const int inf=1e9; void add(int x,int y,int z) { tot++; next[tot]=point[x]; point[x]=tot; remain[tot]=z; v[tot]=y; tot++; next[tot]=point[y]; point[y]=tot; remain[tot]=0; v[tot]=x; } bool bfs(int s,int t) { memset(deep,0x7f,sizeof(deep)); for (int i=s;i<=t;i++) cur[i]=point[i]; deep[s]=0; queue<int> p; p.push(s); while (!p.empty()) { int now=p.front(); p.pop(); for (int i=point[now];i!=-1;i=next[i]) if (remain[i]&&deep[v[i]]>inf) { deep[v[i]]=deep[now]+1; p.push(v[i]); } } if (deep[t]>inf) return false; else return true; } int dfs(int now ,int t,int limit) { if (!limit||now==t) return limit; int flow=0,f; for (int i=cur[now];i!=-1;i=next[i]) { cur[now]=i; if (deep[v[i]]==deep[now]+1&&(f=dfs(v[i],t,min(limit,remain[i])))) { flow+=f; limit-=f; remain[i]-=f; remain[i^1]+=f; if (!limit) break; } } return flow; } int dinic(int s,int t) { int ans=0; while (bfs(s,t)) ans+=dfs(s,t,inf); return ans; } int main() { tot=-1; memset(next,-1,sizeof(next)); memset(point,-1,sizeof(point)); scanf("%d%d",&n,&m); for (i=1;i<=n;i++) { scanf("%d",&f[i]); sum+=f[i]; add(0,i,f[i]); add(i+n,2*n+1,f[i]); } for (i=1;i<=m;i++) { int x,y,z; scanf("%d%d%d",&x,&y,&z); add(x,y+n,z); } printf("%d",sum-dinic(0,2*n+1)); }
相关文章推荐
- 第一章 欢迎来的Code First(5)
- RocEDU.阅读.写作《乌合之众》(四)
- SQLyog软件不显示数据库的问题
- mysql找不到mysql.sock
- TableView的性能优化-主要针对滑动时候出现的卡顿现象
- Xcode中大括号的风格
- 曾经的你,谢谢。
- CCIE学习笔记 3---BGP 团体属性 community
- 链表常见面试题
- 常见假设检验类型对比
- 常见假设检验类型对比
- Unity 编辑器路径设置输入框
- sass使用指南
- 2015届求职经历
- 练习:九九乘法表
- 每日一个小算法(二)-插入排序
- POJ 3050 Hopscotch
- 动画暂停和继续
- 半年总结——不知怎么形容
- 抽象类和接口的区别