hdu6201 思維+最長路(SPFA或Dijkstra)
題意
給你一棵樹,樹上有點權和邊權,讓你選擇起點S到終點T使得T-S-sum最大。(sum是S到T的距離)輸出這個最大值。
題解
這是2017ACM-ICPC瀋陽的網路賽的1008題,這裡不得不吐槽一下這個網路賽的體驗真的很差,好多題的資料都很弱,各種暴力都能過。。。還有個題最差交
這題比賽的時候沒做出來,其實轉化一下就是求最長路的題了。我們新建一個點作為源點(我選的是0),然後建源點到n個點的有向邊,邊權為-w[i](w[i]是i點的點權)。之後新建一個點作為匯點(我選的是n+1),建n個點到匯點的有向邊,邊權為w[i]。最後求源點到匯點的最長路即可。這裡用SPFA和Dijkstra(優先佇列優化)均可。
SPFA程式碼
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int maxn = 1e5+5;
int dist[maxn],in_queue[maxn];
bool vis[maxn];
int n;
struct Edge{
int to,w,next;
}edge[maxn<<2];
int head[maxn],tot;
void add_edge(int u,int v,int w)
{
edge[tot].to = v;
edge[tot].w = w;
edge[tot].next = head[u];
head[u] = tot++;
}
bool SPFA()
{
int cur,next;
queue<int> q;
vis[0] = true;
in_queue[0]++;
dist[0] = 0;
q.push(0);
while(!q.empty())
{
cur = q.front(),q.pop();
vis[cur]=false;
for(int i=head[cur];i!=-1;i=edge[i].next)
{
int to = edge[i].to;
int w = edge[i].w;
if(dist[to]<dist[cur]+w)
{
dist[to] = dist[cur]+w;
if(!vis[to])
{
in_queue[to]++;
if(in_queue[to]>=n+2) return false;
q.push(to);
vis[to] = true;
}
}
}
}
return true;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
tot=0;
memset(head,-1,sizeof(head));
memset(dist,-INF,sizeof(dist));
memset(vis,false,sizeof(vis));
memset(in_queue,0,sizeof(in_queue));
int u,v,w;
for(int i=1;i<=n;i++)
{
scanf("%d",&w);
add_edge(0,i,-w);
add_edge(i,n+1,w);
}
for(int i=1;i<n;i++)
{
scanf("%d%d%d",&u,&v,&w);
add_edge(u,v,-w);
add_edge(v,u,-w);
}
SPFA();
printf("%d\n",dist[n+1]);
}
return 0;
}
Dijkstra程式碼
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int maxn = 1e5+5;
typedef pair<int,int> P;
int dist[maxn];
int n;
struct Edge{
int to,w,next;
}edge[maxn<<2];
int head[maxn],tot;
void add_edge(int u,int v,int w)
{
edge[tot].to = v;
edge[tot].w = w;
edge[tot].next = head[u];
head[u] = tot++;
}
void Dijkstra()
{
priority_queue<P> pq;
P p;
dist[0]=0;
pq.push(P(dist[0],0));
while(!pq.empty())
{
p = pq.top(),pq.pop();
int u = p.second;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v = edge[i].to;
int w = edge[i].w;
if(dist[v]<dist[u]+w)
{
dist[v] = dist[u]+w;
pq.push(P(dist[v],v));
}
}
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
tot=0;
memset(head,-1,sizeof(head));
memset(dist,-INF,sizeof(dist));
int u,v,w;
for(int i=1;i<=n;i++)
{
scanf("%d",&w);
add_edge(0,i,-w);
add_edge(i,n+1,w);
}
for(int i=1;i<n;i++)
{
scanf("%d%d%d",&u,&v,&w);
add_edge(u,v,-w);
add_edge(v,u,-w);
}
Dijkstra();
printf("%d\n",dist[n+1]);
}
return 0;
}
上面是Dijkstra程式碼的,下面是SPFA程式碼的,這題是SPFA跑得快記憶體也少。
相關推薦
hdu6201 思維+最長路(SPFA或Dijkstra)
題意 給你一棵樹,樹上有點權和邊權,讓你選擇起點S到終點T使得T-S-sum最大。(sum是S到T的距離)輸出這個最大值。 題解 這是2017ACM-ICPC瀋陽的網路賽的1008題,這裡不得不吐槽一下這個網路賽的體驗真的很差,好多題的資料都很弱,各種
51nod 1624 取餘最長路 (set+二分查詢) 真.好題
思路: 核心思路是寫出結果的表示式,發現只有兩個變數,所以可以列舉一個變數二分查詢另一個變數。由於依靠結果的表示式,我感覺這個題的思路不好想。 首先說,因為取模後會有後效性,或者說區域性最優不
【思維-最長路】hdu 3696 Farm Game
“Farm Game” is one of the most popular games in online community. In the community each player has a virtual farm. The farmer can decide to plant some kin
LeetCode 845. 陣列中的最長山脈(C++、python)
我們把陣列 A 中符合下列屬性的任意連續子陣列 B 稱為 “山脈”: B.length >= 3 存在 0 < i < B.length - 1 使得 B[0] < B[1] < ... B[i-1] < B
演算法百題001:最長平臺(The Longest Plateau)問題
找出已排序陣列中的最長平臺。平臺是連續的一串值相同的元素,如1,2,2,3中[1], [2, 2], [3]都是平臺。 方案一:常規思路,利用STL的map容器統計每個元素的出現頻數,然後從map容器中選出頻數最大的元素。 /* * Function: longest_
最長線段(幾何證明題)
最長線段(chord.pas/chord.in/chord.out) (LYOI資訊學綜合模擬20090321Problem 1) 問題描述 給定兩個圓各自的圓心座標和半徑長。過其中一個交
最短路演算法(Floyd、Dijkstra)
本節學習指定一個點(源點)到其餘各個頂點的最短路徑,也叫做“單源最短路徑”。例如下圖中的1號頂點到2、3、4、5、6號頂點的最短路徑。 與Floyd演算法一樣,這裡仍然使用二維陣列g來儲存頂點之間邊的關係,初始值如下: 我們還需要用一個一維陣列dis來儲存1號頂點
poj 1932 XYZZY(spfa最長路+判斷正環+floyd求傳遞閉包)
XYZZY Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 4154 Accepted: 1185
HDU 3249 Test for job (有向無環圖上的最長路,DP)
code head struct sin == cout article scanf for ?? 解題思路: 求有向無環圖上的最長路。簡單的動態規劃#include <iostream> #include <cstring> #include
P1807 最長路_NOI導刊2010提高(07)
接下來 for pac ext 輸入輸出 etc while out string 洛谷——P1807 最長路_NOI導刊2010提高(07) 題目描述 設G為有n個頂點的有向無環圖,G中各頂點的編號為1到n,且當為G中的一條邊時有i <
POJ 3592--Instantaneous Transference【SCC縮點新建圖 && SPFA求最長路 && 經典】
col describe sca 搜索 hat style ecif test csdn Instantaneous Transference Time Limit: 5000MS Memory Limit: 65536K
2017CCPC中南地區賽 H題(最長路)
main art spa fine sca using push_back ear 端點 題目地址:202.197.224.59/OnlineJudge2/ 來自湘潭大學OJ,題號:1267。 這裏用到了一個樹的直徑(樹中的最長邊)的結論:當你找到一棵樹的最長邊後,這個樹中
POJ.1752.Advertisement(差分約束 最長路SPFA)
pos 分享 inf Go problem 技術 pty const jks 題目鏈接 \(Description\) 有n個人在一條直線上跑步,每個人的起點 \(Si\)、終點 \(Ei\) 已知;每個點可以放一個廣告牌,一個人i能看到的廣告牌數量為 \(Ei-Si+1\
noip 2009 最優貿易(最短路+反向最長路)
輸出 main 路線 ins 城市 mes 部分 cst don 題目描述 C 國有 n 個大城市和 m 條道路,每條道路連接這 n 個城市中的某兩個城市。任意兩個城市之間最多只有一條道路直接相連。這 m 條道路中有一部分為單向通行的道路,一部分為雙向通行的道路,雙向通行
HDU 6201【最長路+SPFA轉化為流問題求解***】
.com ID printf head eof namespace 題意 scanf pop 題意: 給出一棵生成樹,每個點有一個權值,代表商品的售價,樹上每一條邊上也有一個權值,代表從這條邊經過所需要的花費。現在需要你在樹上選擇兩個點,一個作為買入商品的點,一個作為賣出商
The Largest Clique UVA - 11324( 強連通分量 + dp最長路)
強連通分量 top 起點 printf push fin clas int clu 這題 我剛開始想的是 縮點後 求出入度和出度為0 的點 然後統計個數 用總個數 減去 然而 這樣是不可以的 畫個圖就明白了。。。 如果 減去度為0的點 那麽最後如果出現這
題解報告:hdu 4607 Park Visit(最長路+規律)
inpu follow nodes 一點 dfs ems ios eno sca Problem Description Claire and her little friend, ykwd, are travelling in Shevchenko‘s Park! The
【題解】[牛客網NOIP賽前集訓營-提高組(第六場)]A.最長路 拓撲排序
題目連結 #include<cstdio> #include<queue> #include<cstring> using namespace std; const int N=1e6+10,mod=998244353; st
bzoj1880: [Sdoi2009]Elaxia的路線(spfa,拓撲排序最長路)
1880: [Sdoi2009]Elaxia的路線 Time Limit: 4 Sec Memory Limit: 64 MBSubmit: 1944 Solved: 759[Submit][Status][Disc
BZOJ5450: 轟炸(水題,Tarjan縮點求最長路)
5450: 轟炸 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 43 Solved:18[Submit][Status][Discuss] Description 有n座