問題描述
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 拆成兩個...