HDU 6201 transaction transaction transaction(树上dfs/费用流)
来源:互联网 发布:阿里移动推荐算法总结 编辑:程序博客网 时间:2024/05/22 07:52
Link:
http://acm.hdu.edu.cn/showproblem.php?pid=6201
题意:
有n个城市,每个城市有一本书,买书需要花钱,卖书可以得到钱,并且两个城市之间的距离也有花费。选择两个城市,一个城市买书一个城市卖书,问得到的最大收益。保证给定的n-1条边组成一棵树
解法:
这道题开了好久好久……一直想套费用流结果一直TLE,最后一小时才开始用dfs来写。。衰QAQ
先考虑树上每个点手上有书时的最小花费:这个书可能是在这一点买的,也可能是上一个点带过来的,因此自下往上从叶子结点开始更新,每次递归返回时更新父结点的cost。但是因为这样更新后叶子结点的兄弟还没有更新,所以再从上往下用父结点更新叶子结点,最后拿value-cost即可。
对于样例
3
8 3 16
1 2 2
1 3 1
8
2/ \1
/ \
3 16
第一次更新后 cost[1] = 5 cost[2] = 3 cost[3] = 16
第二次更新后 cost[1] = 5 cost[2] = 3 cost[3] = 6
代码:
#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <vector>#include <cmath>using namespace std;const int N = 1e5+10;const int inf = 1<<30;typedef pair<int,int> p;int vis[N];vector<p> child[N];int value[N];int cost[N];int ans = 0;void dfs1(int x) { vis[x] = 1; cost[x] = value[x]; for(int i = 0; i <child[x].size(); i++) { if(!vis[child[x][i].first]) { dfs1(child[x][i].first); cost[x] = min(cost[x],cost[child[x][i].first]+child[x][i].second); } }}void dfs2(int x) { vis[x] = 1; for(int i = 0; i < child[x].size(); i++) { if(!vis[child[x][i].first] ) { if( cost[x] + child[x][i].second < cost[child[x][i].first] ){ cost[child[x][i].first] = cost[x] + child[x][i].second; } dfs2(child[x][i].first); } } ans = max(ans,value[x] - cost[x]); return;}int main() {// freopen("1.txt","r",stdin); int t; scanf("%d", &t); while(t--) { ans = 0; int n; scanf("%d", &n); for(int i = 1; i <= n; i++) { child[i].clear(); vis[i] = 0; } int x, y ,z; for(int i = 1; i <= n; i++) { scanf("%d", &x); value[i] = x; } for(int i = 1; i < n; i++) { scanf("%d %d %d", &x, &y, &z); child[x].push_back(p(y,z)); child[y].push_back(p(x,z)); } dfs1(1); memset(vis,0,sizeof(vis)); dfs2(1); printf("%d\n",ans); } return 0;}/*238 3 161 2 21 3 1*/
最小费用流解法:
用边限制起点流量之后直接跑费用流,建图的话每个点x连源点s x’连汇点t x’连x。
x到y拆成x→y’ y→x’。
一定要起点流量限制!!!
边数是10n!!!
#include <iostream>#include <queue>#include <stack>#include <vector>#include <set>#include <cmath>#include <map>#include <cstdio>#include <cstring>using namespace std;typedef long long ll; long long _read() { char ch; bool flag = false; int a = 0; while(!((((ch = getchar()) >= '0') && (ch <= '9')) || (ch == '-'))); if(ch != '-') { a *= 10; a += ch - '0'; } else { flag = true; } while(((ch = getchar()) >= '0') && (ch <= '9')) { a *= 10; a += ch - '0'; } if(flag) { a = -a; } return a; } const int MAXN = 200010;const int MAXM = 1200010;const int INF = 0x3f3f3f3f;struct Edge { int to,next,cap,flow,cost;} edge[MAXM];int head[MAXN],tol;int pre[MAXN],dis[MAXN];bool vis[MAXN];int N;//节点总个数,节点编号从0~N-1void init(int n){ N = n; tol = 0; memset(head,-1,sizeof(head));}void addedge(int u,int v,int cap,int cost){ edge[tol].to = v; edge[tol].cap = cap; edge[tol].cost = cost; edge[tol].flow = 0; edge[tol].next = head[u]; head[u] = tol++; edge[tol].to = u; edge[tol].cap = 0; edge[tol].cost = -cost; edge[tol].flow = 0; edge[tol].next = head[v]; head[v] = tol++;}bool spfa(int s,int t){ queue<int>q; for(int i = 0; i < N; i++) { dis[i] = INF; vis[i] = false; pre[i] = -1; } dis[s] = 0; vis[s] = true; q.push(s); while(!q.empty()) { int u = q.front(); q.pop(); vis[u] = false; for(int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if(edge[i].cap > edge[i].flow && dis[v] > dis[u] + edge[i].cost ) { dis[v] = dis[u] + edge[i].cost; pre[v] = i; if(!vis[v]) { vis[v] = true; q.push(v); } } } } if(pre[t] == -1)return false; else return true;}//返回的是最大流,cost存的是最小费用int minCostMaxflow(int s,int t,int &cost,int n){ int flow = 0; cost = 0; while(spfa(s,t)) { if(flow>1) break; int Min = INF; for(int i = pre[t]; i != -1; i = pre[edge[i^1].to]) { if(Min > edge[i].cap - edge[i].flow) Min = edge[i].cap - edge[i].flow; } for(int i = pre[t]; i != -1; i = pre[edge[i^1].to]) { edge[i].flow += Min; edge[i^1].flow -= Min; cost += edge[i].cost * Min; } flow += Min;// cout<<flow<<endl; } return flow;}int main(){// freopen("1.txt","r",stdin); int t; t= _read(); while(t--){ int n; n =_read(); int S = 0,s = 2*n+1, t = 2 * n + 2; init(n*2+3); int x, y ,z; for(int i = 1; i <= n; i++){ x = _read(); addedge(s,i,1,x); addedge(i+n,t,1,-x); addedge(i+n,i,1,0); } for(int i = 1; i < n; i++){ x=_read(),y=_read(),z=_read(); addedge(x,y+n,1,z); addedge(y,x+n,1,z); } x = 0; addedge(S,s,1,0);// cout<<"===="<<endl;// continue; int ans = minCostMaxflow(S,t,x,n); x = -x; if(x<0) x=0; printf("%d\n",x); } return 0;}
阅读全文
1 0
- HDU 6201 transaction transaction transaction(树上dfs/费用流)
- 【HDU 6201】transaction transaction transaction 【费用流】
- HDU 6201 transaction transaction transaction [网络流]
- HDU 6201 transaction transaction transaction(网络流+最短路)
- hdu 6201transaction transaction transaction
- HDU 6201 transaction transaction transaction
- hdu 6201 transaction transaction transaction
- HDU 6201 transaction transaction transaction
- hdu-6201 transaction transaction transaction
- hdu 6201 transaction transaction transaction
- transaction transaction transaction HDU
- transaction transaction transaction HDU
- HDU 6201 transaction transaction transaction(树形dp)
- hdu 6201 transaction transaction transaction(最长路)
- HDU 6201 transaction transaction transaction(SPFA模板)
- HDU 6201 transaction transaction transaction (最长路)
- HDU 6201 transaction transaction transaction (树形dp)
- Hdu 6201 transaction transaction transaction(最长路)
- 在CentOS7下将nginx添加到systemctl
- 基础代码-维护图的连通性
- C++连接Mysql
- Makefile基础教程 10
- iOS学习笔记-133.RunLoop01——基础知识
- HDU 6201 transaction transaction transaction(树上dfs/费用流)
- 洛谷 P1967 货车运输(Kruskal最大生成树&&倍增lca)
- hadoop初识之十一:mapreduce编写格式与示例, 并在yarn上运行
- ICPC2017网络赛(沈阳)1008&HDU6201transaction(spfa 费用流)
- Maven 中使用本地 jar 包
- git如何配置ssh
- Qt-Widget窗体无法最大化问题解决
- 关于项目在IIS中启动后报handlers红色错误的解决方案
- 华为机试在线训练–牛客网(python)第二部分