URAL 1076:费用流解法
来源:互联网 发布:400÷1.25的简便算法 编辑:程序博客网 时间:2024/06/08 17:25
题意:
数字N表示有N个垃圾箱,而且刚好存在N类垃圾
每行输入的是第i个垃圾箱装有 x 数量 的第j类垃圾;
现在要你将这些垃圾分类,也就是把同类垃圾放在同一个垃圾箱里,
而且每个垃圾箱只能放一类垃圾。。。
每次把一个单元垃圾从一个垃圾箱移动到另一个垃圾箱就要1 effort;
求最小的 effort;
比赛时看数据开始以为dp能行,后来测试数据发现自己的状态转移方程是错的。。。
根本没有最优子结构;
比赛完后看题解,原来是 二分图的最佳匹配,
以前只会 最大匹配,,,然后看了一晚上,实在是难以理解
大家可以去看看
@wanggp3
http://www.cnblogs.com/wanggp3/p/3762568.html
最后实在不行了,突然发现好像最小费用流可以做。。。
只要自己建立 超级源,超级汇就可以了(常用套路)
1–N点 表示垃圾种类,N+1–N+N点 表示垃圾箱
每类垃圾 对 每个垃圾箱之间都存在边,容量为1,而费用就是
该类垃圾的总数-在该垃圾箱里已有的该类垃圾数量(sum[j] - map[i][j])
超级源点0 与 1–N 点(垃圾种类)都有边,容量为1, 费用为0;
超级汇点N+N+1 与 N+1–N+N点(垃圾箱)都有边,容量为1,费用为0;
然后计算,
最开始提交时超时了QAQ。。。以为费用流会超时。。。
后来网上看到有人说是可以用费用流做的,然后回来检查一下。。。
CHX 发现了 是在
for(int i=0; i
#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<vector>#include<queue>#include<cmath>using namespace std;const int INF = 1e9+9;const int MAXN = 350;struct Node{ int from; //左 int to; //右 int cap; //容量 int flow; //流量 int cost; //费用};vector <Node> e; ///一条边的所有属性vector <int> v[MAXN]; ///记录边的位置int vis[MAXN];int dis[MAXN];int father[MAXN],pos[MAXN]; ///father保存父节点, pos保存capvoid Clear(){ for(int i=0; i<=MAXN; ++i) v[i].clear(); e.clear();}void add_Node(int from, int to, int cap, int cost){ e.push_back((Node){from,to,cap,0,cost}); e.push_back((Node){to,from,0,0,-cost}); ///反向边 int len = e.size()-1; v[to].push_back(len); v[from].push_back(len-1);}bool SPFA(int s, int t, int& flow, int& cost){ //memset(dis,0,sizeof(dis)); for(int i=0; i<MAXN; ++i) dis[i] = INF; memset(vis,0,sizeof(vis)); dis[s] = 0; ///最短路径,即 最小费用 vis[s] = 1; ///标记是否在队列里 father[s] = 0; pos[s] = INF; queue<int> q; q.push(s); // vector<int>::iterator it; while(!q.empty()) { int u = q.front(); q.pop(); vis[u] = 0; // for(it = v[u].begin();it!=v[u].end();it++) // { //int i = it - v[u].end(); // Node &tmp = e[(*it)]; // } int s1 = v[u].size(); for(int i=0; i<s1; ++i) { Node &tmp = e[v[u][i]]; if(tmp.cap> tmp.flow && dis[tmp.to]>dis[u]+tmp.cost) { dis[tmp.to] = dis[u] + tmp.cost; father[tmp.to] = v[u][i]; // (*it); pos[tmp.to] = min(pos[u], tmp.cap-tmp.flow); ///更新边的剩余容量(最大流量),记录最小的 if(!vis[tmp.to]) { q.push(tmp.to); vis[tmp.to] = 1; } } } } if(dis[t]==INF) return false; flow += pos[t]; cost += dis[t]*pos[t]; int t2 = t; while(t2 != s) { e[father[t2]].flow += pos[t]; e[father[t2]^1].flow -= pos[t]; t2 = e[father[t2]].from; }return true;}int Min_Cost(int s,int t){ int flow = 0; int cost = 0; while(SPFA(s,t,flow,cost)); return cost;}int all_trash[MAXN];int map1[MAXN][MAXN];int main(){ int N; while(scanf("%d",&N)!=EOF) { Clear(); memset(all_trash,0,sizeof(all_trash)); int x; for(int i=1; i<=N ;++i) for(int j=1; j<=N; ++j) { scanf("%d",&map1[i][j]); all_trash[j] += map1[i][j]; } int u,v,w; ///容量是1 for(int i=1; i<=N ;++i) for(int j=1; j<=N; ++j) { //scanf("%d%d%d",&u,&v,&w); u = i; v = j+N; w = all_trash[j] - map1[i][j]; add_Node(u,v,1,w); // add_Node(v,u,1,w); ///双向边 } for(int i=1; i<=N; ++i) add_Node(0,i,1,0); for(int j=N+1; j<=N+N; ++j) add_Node(j,N+N+1,1,0); printf("%d\n",Min_Cost(0,N+N+1)); } return 0;}``
“`
0 0
- URAL 1076:费用流解法
- Ural 1076 费用流
- Ural-1076 Trash(最小费用最大流算法)
- Ural-1076 Trash(最小费用最大流算法)
- ural 1076 Trash 二分图最大权匹配(费用流实现)
- POJ 2516 Minimum Cost (最小费用最大流,KM解法)
- NOIP2011Day2第三题观光公交的费用流解法
- hdu1853 Cyclic Tour . 最小费用流 StL解法
- 费用流!
- 费用流
- 费用流
- 费用流
- 费用流
- hdu4862 2014多校B题/ 费用流(最优情况下用不大于K条路径覆盖)(不同的解法)
- URAL
- 【ural】
- URAL
- URAL
- hdu5807 dp
- CSS3动画
- 解决Sublime Text 3在GBK编码下的中文乱码问题
- 微信开发学习第一天- 群发功能
- 常用正则表达式
- URAL 1076:费用流解法
- 欢迎使用CSDN-markdown编辑器
- hdu 5800 To My Girlfriend(2016 Multi-University Training Contest 6——DP)
- 尼姆博弈
- ex11.py
- 一位工程师的FPGA项目开发经验总结
- 猴子分桃问题
- 多线程 NSThread,NSOperation,GCD
- ex12.py