题目列表:
1. https://cn.vjudge.net/problem/HDU-5960
2. hdu6181 第k短路 – 双向边
3. poj 2449 最裸的模板
4. 2018-沈阳网络赛-D-K短路 https://nanti.jisuanke.com/t/31445
总结 :除了第一题,其他的都是很裸的模板题,所以只介绍第一题。
其中第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
#include
#include
#include
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 ;
}
分层最短路建图
https://blog.csdn.net/GYH0730/article/details/82289927