hdu2017沈阳网络赛(2)transaction(从最短路到树dp)
来源:互联网 发布:linux ln 删除 编辑:程序博客网 时间:2024/05/01 06:13
题面:
Kelukin is a businessman. Every day, he travels around cities to do some business. On August 17th, in memory of a great man, citizens will read a book named "the Man Who Changed China". Of course, Kelukin wouldn't miss this chance to make money, but he doesn't have this book. So he has to choose two city to buy and sell.
As we know, the price of this book was different in each city. It isai yuan in i t city. Kelukin will take taxi, whose price is 1 yuan per km and this fare cannot be ignored.
There aren−1 roads connecting n cities. Kelukin can choose any city to start his travel. He want to know the maximum money he can get.
As we know, the price of this book was different in each city. It is
There are
思维过程:元素变量有点值(valu),边值(cost)。图的特征为n-1条边(树)。
简化题意:在树上找到两点使得valu(v)-valu(u)-cost(v,u)最大。这里的cost(v,u)应该指的是u,v之间的最短路。显然这种式子的最大值应该能用费用流做,但是看到这种只和源点和汇点有关的式子就定式的觉得最短路也能做,然后就试着用dijstra写了一份,然后加上一些check,比如如果按顺序找到从某一点为源点的最大值,在对点u做dij时如果有点dist【v】<=0的话就直接check【v】=false,感觉能剪掉不上的点,但是还是t了(剪不过来吧。。)
失败的代码:
int min_max(int n,int u){
for (int i=1; i<=n; i++) {
vis[i]=false;
}
int maxmum=0;
priority_queue<qnode>que;
while (!que.empty()) {
que.pop();
}
que.push(qnode(u,0));
qnode tmp;
while (!que.empty()) {
tmp=que.top();
que.pop();
int l=tmp.v;
if (vis[l]||!check[l]) {
continue;
}
vis[l]=true;
for (int i=0; i<g[l].size(); i++) {
int v=g[l][i].v;
int cost=g[l][i].cost;
int f=dist[l]+cost-2*(valu[u]-valu[v])-dist[v];
if (!vis[v]&&f>0) {
dist[v]=dist[l]+cost;
que.push(qnode(v,dist[v]));
if (dist[v]>maxmum){
maxmum=dist[v];
}
}
}
}
for (int i=1; i<=n; i++) {
if (dist[i]<=0) {
check[i]=false;
}
}
return maxmum;
}
for (int i=1; i<=n; i++) {
if (check[i]) {
int k=min_max(n, i);
if (k>minmum) {
minmum=k;
}
}
}
for (int i=1; i<=n; i++) {
vis[i]=false;
}
int maxmum=0;
priority_queue<qnode>que;
while (!que.empty()) {
que.pop();
}
que.push(qnode(u,0));
qnode tmp;
while (!que.empty()) {
tmp=que.top();
que.pop();
int l=tmp.v;
if (vis[l]||!check[l]) {
continue;
}
vis[l]=true;
for (int i=0; i<g[l].size(); i++) {
int v=g[l][i].v;
int cost=g[l][i].cost;
int f=dist[l]+cost-2*(valu[u]-valu[v])-dist[v];
if (!vis[v]&&f>0) {
dist[v]=dist[l]+cost;
que.push(qnode(v,dist[v]));
if (dist[v]>maxmum){
maxmum=dist[v];
}
}
}
}
for (int i=1; i<=n; i++) {
if (dist[i]<=0) {
check[i]=false;
}
}
return maxmum;
}
for (int i=1; i<=n; i++) {
if (check[i]) {
int k=min_max(n, i);
if (k>minmum) {
minmum=k;
}
}
}
但是在想到check后意识到可能是没有考虑图的特殊性,图是一个树,两点间不存在最短路之说(路径唯一),所以用最短路实际上是一种浪费,同时也要充分利用类似check的条件,dp就是一个能做到这两件事的工具,在树上,当然就树dp了;
代码:
#include <iostream>
#include <vector>
#include <cstdio>
using namespace std;
const int maxn=1e5+5;
struct edge{
int v,cost;
edge(int qv,int qc):v(qv),cost(qc){}
};
vector<edge>g[maxn];
void addedge(int u,int v,int ff){
g[u].push_back(edge(v,ff));
}
int fa[maxn];
void buildtree(int x,int y){
fa[x]=y;
for (int i=0; i<g[x].size(); i++) {
int v=g[x][i].v;
if (v!=y) {
buildtree(v, x);
}
}
}
int valu[maxn];
int maxmum;
int dp[maxn][2];
void dfs(int u){
dp[u][0]=-valu[u];
dp[u][1]=valu[u];
for (int i=0; i<g[u].size(); i++) {
int v=g[u][i].v;
if (v!=fa[u]) {
dfs(v);
dp[u][0]=max(dp[u][0],dp[v][0]-g[u][i].cost);
dp[u][1]=max(dp[u][1],dp[v][1]-g[u][i].cost);
}
maxmum=max(maxmum,dp[u][0]+dp[u][1]);
}
}
int main(){
int t;
cin>>t;
while (t--) {
int n;
cin>>n;
maxmum=0;
for (int i=1; i<=n; i++) {
g[i].clear();
}
for (int i=1; i<=n; i++) {
scanf("%d",&valu[i]);
}
for (int i=0; i<n-1; i++) {
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
addedge(x, y, z);
addedge(y, x, z);
}
buildtree(1, -1);
dfs(1);
cout<<maxmum<<endl;
}
return 0;
}
#include <vector>
#include <cstdio>
using namespace std;
const int maxn=1e5+5;
struct edge{
int v,cost;
edge(int qv,int qc):v(qv),cost(qc){}
};
vector<edge>g[maxn];
void addedge(int u,int v,int ff){
g[u].push_back(edge(v,ff));
}
int fa[maxn];
void buildtree(int x,int y){
fa[x]=y;
for (int i=0; i<g[x].size(); i++) {
int v=g[x][i].v;
if (v!=y) {
buildtree(v, x);
}
}
}
int valu[maxn];
int maxmum;
int dp[maxn][2];
void dfs(int u){
dp[u][0]=-valu[u];
dp[u][1]=valu[u];
for (int i=0; i<g[u].size(); i++) {
int v=g[u][i].v;
if (v!=fa[u]) {
dfs(v);
dp[u][0]=max(dp[u][0],dp[v][0]-g[u][i].cost);
dp[u][1]=max(dp[u][1],dp[v][1]-g[u][i].cost);
}
maxmum=max(maxmum,dp[u][0]+dp[u][1]);
}
}
int main(){
int t;
cin>>t;
while (t--) {
int n;
cin>>n;
maxmum=0;
for (int i=1; i<=n; i++) {
g[i].clear();
}
for (int i=1; i<=n; i++) {
scanf("%d",&valu[i]);
}
for (int i=0; i<n-1; i++) {
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
addedge(x, y, z);
addedge(y, x, z);
}
buildtree(1, -1);
dfs(1);
cout<<maxmum<<endl;
}
return 0;
}
阅读全文
0 0
- hdu2017沈阳网络赛(2)transaction(从最短路到树dp)
- HDU沈阳网络赛:transaction transaction transaction(树形dp & 最短路)
- hdu2017沈阳网络赛card(结论水题)
- 2017沈阳网络赛 1008 HDU 6201 transaction transaction transaction(树形dp)
- ICPC2017网络赛(沈阳)1008 transaction transaction transaction——树形DP
- HDU 6201 transaction transaction transaction(网络流+最短路)
- hdu2017青岛网络赛Zuma(区间dp)
- 【2017沈阳网络赛】1008 hdu6201 transaction transaction transaction 树形dp
- hdu5521 ICPC2015沈阳现场赛(最短路)
- hdu2017沈阳网络赛补题(一)mustedge mustedge(数剖求lca+树状数组)
- HDU 6201 transaction transaction transaction &&沈阳网络赛1008
- HDU 6201 transaction transaction transaction (2017沈阳网络赛
- HDU 6201 transaction transaction transaction (2017沈阳网络赛
- hdu6201 transaction transaction transaction 树形dp || 最短路
- hdu5900(2016沈阳网络赛1009区间dp)
- ICPC2015(沈阳)HDU5521 建图技巧+最短路
- hdu2017青岛网络赛Apple(java练习题)
- 2015年沈阳区域赛M题 Meeting(最短路)
- TCP/IP协议系列文章
- 嵌入式多路温湿度监控系统(九菜单配置程序)
- Jmeter--HTTP取样器使用数据库中数据进行测试
- Quatus联合modelsim仿真无法产生波形原因分析
- Linux电源管理(三)电源管理接口
- hdu2017沈阳网络赛(2)transaction(从最短路到树dp)
- Servlet的概述以及生命周期
- 我的努力很久没有回报的感受2017年10月三日
- 参数化查询'(@StudentNo nvarchar(3),@CardID nvarchar(1),@UserID nvarchar(400'需要参数@UserID'),但是未提供该参数。)
- Python——list常见用法
- gdb调试
- 路径分析
- 滤镜 黑白图片
- 设计模式_2:策略模式