k短路模板 整理
阿新 • • 發佈:2019-02-07
總結 :除了第一題,其他的都是很裸的模板題,所以只介紹第一題。
其中第2題是求1-n次短路,且是雙向邊
第2題直接求k短路,沒有的話輸出-1,單向邊
第4題判斷k短路是否小於等於T,單向邊
第一題 題意:給定n條邊 每條邊(cost,cost2,color)
color只有0,1 現在讓你從這些邊中求一個子序列,這個子序列的權值
是這樣計算的,假設你選了h個點,從1-h,一開始 now = 0
if now=0 ans+=cost
else ans+=cost2 然後now = 該條邊的color建圖參考
我是看上面這篇部落格看懂的,但是上面這篇部落格裡有一些錯誤,
首先把每一個點拆成3個點,i,i+n,i+n+n
然後i+n層作為cost層,i+n+n作為cost2層
如果i!=n 每個點都向當前點的下一個點進行轉移連一條權值為0的邊,
層與層之間的轉移通過i層進行轉移,通過color取值向cost層和cost2層進行連邊
最後每一層的終點都向終點連一條權值為0的邊
由於一開始now = 0,所以起點是點n+1
出處:無敵k短路
#include <stdio.h>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std ;
typedef long long LL ;
typedef pair < int, int > pii ;
typedef pair < LL, int > pli ;
typedef unsigned long long ULL ;
#define clr( a , x ) memset ( a , x , sizeof a )
#define st first
#define ed second
const int MAXN = 100005 ;
const int BLOCK = 22 ;
const LL INF = 1e18 ;
namespace Leftist_Tree
{
struct Node
{
int l, r, x, h ;
LL val ;
} T[MAXN * 200] ;
int Root[MAXN] ;
int node_num ;
int newnode ( const Node& o )
{
T[node_num] = o ;
return node_num ++ ;
}
void init ()
{
node_num = 1 ;
T[0].l = T[0].r = T[0].x = T[0].h = 0 ;
T[0].val = INF ;
}
int merge ( int x, int y )
{
if ( !x ) return y ;
if ( T[x].val > T[y].val ) swap ( x, y ) ;
int o = newnode ( T[x] ) ;
T[o].r = merge ( T[o].r, y ) ;
if ( T[T[o].l].h < T[T[o].r].h ) swap ( T[o].l, T[o].r ) ;
T[o].h = T[T[o].r].h + 1 ;
return o ;
}
void insert ( int& x, LL val, int v )
{
int o = newnode ( T[0] ) ;
T[o].val = val, T[o].x = v ;
x = merge ( x, o ) ;
}
void show ( int o )
{
printf ( "%d %lld %lld %lld\n", o, T[o].val, T[T[o].l].val, T[T[o].r].val ) ;
if ( T[o].l ) show ( T[o].l ) ;
if ( T[o].r ) show ( T[o].r ) ;
}
}
using namespace Leftist_Tree ;
vector < pii > G[MAXN], E[MAXN] ;
int vis[MAXN] ;
int in[MAXN], p[MAXN] ;
LL d[MAXN] ;
int s, t ;
int n, m, k ;
void addedge ( int u, int v, int c )
{
G[u].push_back ( pii ( v, c ) ) ;
E[v].push_back ( pii ( u, c ) ) ;
}
void dij ()
{
priority_queue < pli > q ;
d[t] = 0 ;
q.push ( pli ( 0, t ) ) ;
while ( !q.empty () )
{
int u = q.top ().ed ;
q.pop () ;
if ( vis[u] ) continue ;
vis[u] = 1 ;
for ( int i = 0 ; i < E[u].size () ; ++ i )
{
int v = E[u][i].st ;
if ( d[v] > d[u] + E[u][i].ed )
{
p[v] = u ;
d[v] = d[u] + E[u][i].ed ;
q.push ( pli ( -d[v], v ) ) ;
}
}
}
}
void dfs ( int u )
{
if ( vis[u] ) return ;
vis[u] = 1 ;
if ( p[u] ) Root[u] = Root[p[u]] ;
int flag = 1 ;
for ( int i = 0 ; i < G[u].size () ; ++ i )
{
int v = G[u][i].st ;
if ( d[v] == INF ) continue ;
if ( p[u] == v && d[u] == G[u][i].ed + d[v] && flag )
{
flag = 0 ;
continue ;
}
LL val = d[v] - d[u] + G[u][i].ed ;
insert ( Root[u], val, v ) ;
}
for ( int i = 0 ; i < E[u].size () ; ++ i )
{
if ( p[E[u][i].st] == u ) dfs ( E[u][i].st ) ;
}
}
void solve ()
{
for ( int i = 1 ; i <= n ; ++ i )
{
G[i].clear () ;
E[i].clear () ;
d[i] = INF ;
vis[i] = 0 ;
p[i] = 0 ;
}
for ( int i = 0 ; i < m ; ++ i )
{
int u, v, c ;
scanf ( "%d%d%d", &u, &v, &c ) ;
addedge ( u, v, c ) ;
addedge ( v, u, c ) ;
}
//scanf ( "%d%d%d", &s, &t, &k ) ;
s = 1;
t = n;
k = 2;
dij () ;
if ( d[s] == INF )
{
printf ( "-1\n" ) ;
return ;
}
if ( s != t ) -- k ;
if ( !k )
{
printf ( "%lld\n", d[s] ) ;
return ;
}
for ( int i = 1 ; i <= n ; ++ i )
{
vis[i] = 0 ;
}
init () ;
Root[t] = 0 ;
dfs ( t ) ;
priority_queue < pli, vector < pli >, greater < pli > > q ;
if ( Root[s] ) q.push ( pli ( d[s] + T[Root[s]].val, Root[s] ) ) ;
while ( k -- )
{
if ( q.empty () )
{
printf ( "-1\n" ) ;
return ;
}
pli u = q.top () ;
q.pop () ;
if ( !k )
{
printf ( "%lld\n", u.st ) ;
return ;
}
int x = T[u.ed].l, y = T[u.ed].r, v = T[u.ed].x ;
if ( Root[v] ) q.push ( pli ( u.st + T[Root[v]].val, Root[v] ) ) ;
if ( x ) q.push ( pli ( u.st + T[x].val - T[u.ed].val, x ) ) ;
if ( y ) q.push ( pli ( u.st + T[y].val - T[u.ed].val, y ) ) ;
}
}
int main ()
{
int TT;
scanf("%d",&TT);
while ( TT-- )
{
scanf ( "%d%d", &n, &m );
solve();
}
return 0 ;
}