USACO 2009 JAN GOLD 安全路徑

2021-10-09 08:10:05 字數 3150 閱讀 2475

問題描述

gremlins最近在農場上氾濫,它們經常會阻止牛們從農莊(牛棚_1)走到別的牛棚(牛_i的目的地是牛棚_i)。每乙個gremlin只認識牛_i並且知道牛_i一般走到牛棚_i的最短路經。所以它們在牛_i到牛棚_i之前的最後一條牛路上等牛_i,當然,牛不願意遇到gremlins,所以準備找一條稍微不同的路經從牛棚_1走到牛棚_i,所以,請你為每一頭牛_i找出避免gremlin_i的最短路經的長度。

和以往一樣,農場上的m (2 <= m <= 200,000)條雙向牛路編號為1..m並且能讓所有牛到達它們的目的地,n(3 <= n <= 100,000)個編號為1..n的牛棚。牛路i連線牛棚a_i (1 <= a_i <= n)和b_i (1 <= b_i <= n)並且需要時間t_i (1 <=t_i <= 1,000)通過。沒有兩條牛路連線同樣的牛棚,所有牛路滿足a_i!=b_i。在所有資料中,牛_i使用的牛棚_1到牛棚_i的最短路經是唯一的。

以下是乙個牛棚,牛路和時間的例子:

輸入格式

第一行:兩個空格分開的數n和m;

第2..m+1行:三個空格分開的數a_i, b_i,和t_i

輸出格式

第1..n-1行:第i行包含乙個數,從牛棚_1到牛棚_i+1並且避免從牛棚1到牛棚i+1最短路經上最後一條牛路的最少的時間。如果這樣的路經不存在,輸出-1。

樣例輸入

4 51 2 2

1 3 2

3 4 4

3 2 1

2 4 3

樣例輸出33

6提示【資料範圍】

20%的資料滿足,n<=200;

50%的資料滿足,n<=3000

100%的資料滿足,n<=100,000

令dis為最短路跑出來的陣列

首先做了最短路後就變成了乙個最短路樹,在這顆樹上進行操作。計算答案顯然對於乙個點i,答案應該是i的子樹中的乙個點j連一條不在整棵樹上的邊到不屬於i子樹的乙個點k,答案即為min(dis[j]+dis[k]-w[k][j])-dis[i]

,那麼考慮一條不在樹上的邊,顯然,這條邊兩個點x,y到其lca的路徑中的點會有貢獻,且不包括lca,那麼就可以直接修改這條鏈上的節點的答案,貢獻為dis[x]+dis[y]-w[i][j]用線段樹維護答案的那個min()中的值,最後算答案的時候再減dis[i]

開始一直想的是怎樣考慮乙個點的答案,其實需要換一種思路,考慮邊對點的貢獻

#include using namespace std;

#define ll long long

const ll inf = 1e9 + 7;

const int maxn = 100003;

int n , m , cnt ;

struct edgeg[maxn<<2];

vectorg1[maxn];

int fa[maxn] , id[maxn] , ncnt , siz[maxn] , top[maxn] , hei[maxn] , zson[maxn];

struct node

node( int v , ll w )

friend bool operator < ( node a , node b )

};struct treetre[maxn<<2];

int head[maxn];

inline void add_edge( int x , int y , int w )

ll dis[maxn];

priority_queueq;

void dfs( int x , int f )

}inline void dfs1( int x, int f )

}inline void build( int i , int l , int r )

int mid = ( l + r) >> 1;

build( i << 1 , l , mid );

build( i << 1 | 1 , mid + 1, r );

tre[i].minn = min( tre[i<<1].minn , tre[i<<1|1].minn );

}inline void pushdown( int i )

}inline void modify( int i , int l , int r , ll delta )

pushdown( i );

modify( i <<1 , l , r , delta );

modify( i << 1 | 1 , l , r, delta );

tre[i].minn = min( tre[i<<1].minn ,tre[i<<1|1].minn );

}inline ll query( int i , int l , int r )

pushdown( i );

ll ans = query( i <<1 , l , r );

ans = min( ans , query( i << 1 | 1 , l , r ) );

tre[i].minn = min( tre[i<<1].minn ,tre[i<<1|1].minn );

return ans;

}inline int lca( int x , int y )

if( hei[x] > hei[y] ) return y;

return x;

}inline void change( int x, int y , ll z )

if( x == y ) return;

modify( 1 , id[y] + 1 , id[x] , z );

}int main()

memset( dis ,inf , sizeof( dis ) );

dis[1] = 0;

q.push( node( 1,0 ) );

while( !q.empty() )}}

for( int i = 0 ; i < cnt ; i ++ )

}hei[1] = 1;

dfs( 1 , 0 );

dfs1( 1, 1 );

build( 1 , 1 , n );

for( int i = 0 ; i < cnt ; i += 2 )

for( int i = 2 ; i <= n ; i ++ )

return 0;

}

P2943 Usaco2009 Mar 打掃衛生

神題一道 變數異常複雜,請在結合程式及注釋的情況下 根據題意不難看出,在選擇的一段區間內,最多有 n sqrt n 種不同的食物。據此設計dp陣列f i 表示i時的最小代價。設計輔助陣列pos j 表示最多選j種食物時區間左端點位置。思考 遍歷到i時,使區間食物種數不變應滿足什麼條件?得出 若上乙個...

USACO 修理牛棚

同樣是一道貪心題,我的思路是用乙個陣列存下所有的空擋,對空擋進行排序,然後再在總長度中減去前m 1 大的空檔長度。關鍵還是理解題意。貌似洛谷 oj不支援 int min 之類的。還有要對初始資料排一次序,害我 wa了一次。include include includeusing namespace ...

USACO 奶牛電信

題目鏈結 洛谷1345 題目大意 給出乙個 n 個點 m條邊的無向圖,與 s,t 問至少刪去多少個點,使 s,t 不連通。n 100,m 600 分析 1.對於這種分離s,t 的題,考慮最大流 最小割的方法。2.然而題目要求割點,而不是割邊,怎麼辦?這就是一種經典的拆點題。3.把每個點 i 拆成兩個...