之前本沙茶成功地在网络流图中搞出Dancing Link边表,那么对于一般的图,是否也能用Dancing Link边表呢?答案是肯定的。
struct
edge {
int a, b, len, pre, next;
} ed[MAXM];
初始化表头:
int a, b, len, pre, next;
} ed[MAXM];
void
init_d()
{
re(i, n) ed[i].a = ed[i].pre = ed[i].next = i;
if (n % 2 ) m = n + 1 ; else m = n;
}
加边(这里是加有向边,如果加无向边的话,再加一条边<b, a, len>即可):
{
re(i, n) ed[i].a = ed[i].pre = ed[i].next = i;
if (n % 2 ) m = n + 1 ; else m = n;
}
void
add_edge(
int
a,
int
b,
int
len)
{
ed[m].a = a; ed[m].b = b; ed[m].len = len; ed[m].pre = ed[a].pre; ed[m].next = a; ed[a].pre = m; ed[ed[m].pre].next = m ++ ;
}
在一般的图中应用Dancing Link边表的优势:【1】能够有效处理删边删点问题;【2】在无向图中,能够很快找到一条边对应的逆向边;【3】最大的优势是:如果要从某一条单点链表(其实整个边表可以看成N个单点链表的并,N为图中的点数)的中间开始遍历,或者逆向遍历整个表的话,一般的邻接链表几乎不可能完成,一般的边表也很麻烦,这种Dancing Link边表则可以很快搞定。不过它也有缺点:空间消耗比邻接链表和一般边表大一些(不过这个影响不大)。
{
ed[m].a = a; ed[m].b = b; ed[m].len = len; ed[m].pre = ed[a].pre; ed[m].next = a; ed[a].pre = m; ed[ed[m].pre].next = m ++ ;
}
【应用实例】 PKU1062(PKU上少有的中文题)
很水的最短路问题。将每个物品当成一个点,若j可作为i的优惠品则连边<i, j>,边权为优惠价格,然后,枚举等级限制(由于物品1是必须选的,因此设最大等级限制为lmt,物品1的等级为V,则可在[V-lmt, V]范围内枚举最低等级,最高等级就是(最低等级+lmt)),将所有不在等级限制内的点全部删除(其实不用真删除,只要设一个del数组避开它们即可),求从结点1到各结点的最短路,则min(dist[i]+cs[i])(dist[i]表示1到i的最短路,cs[i]表示直接购买物品i的价格)就是结果。
代码(2Y,一开始把solve里的g[j]弄成g[i]了囧……静态查错V5啊……神犇不要鄙视):
#include
<
iostream
>
#include < stdio.h >
#include < queue >
#include < utility >
using namespace std;
#define re(i, n) for (int i=0; i<n; i++)
#define re3(i, l, r) for (int i=l; i<=r; i++)
typedef pair < int , int > i_i;
typedef priority_queue < i_i, vector < i_i > , greater < i_i > > pqi_i;
const int MAXN = 100 , MAXM = 30000 , INF = ~ 0U >> 2 ;
struct edge {
int a, b, len, pre, next;
} ed[MAXM];
int n, m, s, lmt, cs[MAXN], g[MAXN], dist[MAXN], res = INF;
bool del[MAXN];
pqi_i q;
void init_d()
{
re(i, n) ed[i].a = ed[i].pre = ed[i].next = i;
if (n % 2 ) m = n + 1 ; else m = n;
}
void add_edge( int a, int b, int len)
{
ed[m].a = a; ed[m].b = b; ed[m].len = len; ed[m].pre = ed[a].pre; ed[m].next = a; ed[a].pre = m; ed[ed[m].pre].next = m ++ ;
}
void init()
{
int b0, x, y;
scanf( " %d%d " , & lmt, & n);
init_d();
re(i, n) {
scanf( " %d%d%d " , & cs[i], & g[i], & x);
re(j, x) {
scanf( " %d%d " , & b0, & y);
add_edge(i, -- b0, y);
}
}
}
void sol1()
{
re(i, n) if ( ! del[i]) dist[i] = INF + 1 ; q.push(i_i( 0 , s));
int i, j, d0, d1;
while ( ! q.empty()) {
d0 = q.top().first; i = q.top().second; q.pop();
if (dist[i] == INF + 1 ) {
dist[i] = d0;
for ( int p = ed[i].next; p != i; p = ed[p].next) {
j = ed[p].b;
if ( ! del[j]) {
d1 = d0 + ed[p].len; q.push(i_i(d1, j));
}
}
}
}
re(i, n) if ( ! del[i]) {
d0 = cs[i] + dist[i];
if (d0 < res) res = d0;
}
}
void solve()
{
int lf, rt; s = 0 ;
re3(i, 0 , lmt) {
lf = g[s] - i; rt = lf + lmt;
re(j, n) del[j] = g[j] < lf || g[j] > rt;
sol1();
}
}
void pri()
{
printf( " %d\n " , res);
}
int main()
{
init();
solve();
pri();
return 0 ;
}
#include < stdio.h >
#include < queue >
#include < utility >
using namespace std;
#define re(i, n) for (int i=0; i<n; i++)
#define re3(i, l, r) for (int i=l; i<=r; i++)
typedef pair < int , int > i_i;
typedef priority_queue < i_i, vector < i_i > , greater < i_i > > pqi_i;
const int MAXN = 100 , MAXM = 30000 , INF = ~ 0U >> 2 ;
struct edge {
int a, b, len, pre, next;
} ed[MAXM];
int n, m, s, lmt, cs[MAXN], g[MAXN], dist[MAXN], res = INF;
bool del[MAXN];
pqi_i q;
void init_d()
{
re(i, n) ed[i].a = ed[i].pre = ed[i].next = i;
if (n % 2 ) m = n + 1 ; else m = n;
}
void add_edge( int a, int b, int len)
{
ed[m].a = a; ed[m].b = b; ed[m].len = len; ed[m].pre = ed[a].pre; ed[m].next = a; ed[a].pre = m; ed[ed[m].pre].next = m ++ ;
}
void init()
{
int b0, x, y;
scanf( " %d%d " , & lmt, & n);
init_d();
re(i, n) {
scanf( " %d%d%d " , & cs[i], & g[i], & x);
re(j, x) {
scanf( " %d%d " , & b0, & y);
add_edge(i, -- b0, y);
}
}
}
void sol1()
{
re(i, n) if ( ! del[i]) dist[i] = INF + 1 ; q.push(i_i( 0 , s));
int i, j, d0, d1;
while ( ! q.empty()) {
d0 = q.top().first; i = q.top().second; q.pop();
if (dist[i] == INF + 1 ) {
dist[i] = d0;
for ( int p = ed[i].next; p != i; p = ed[p].next) {
j = ed[p].b;
if ( ! del[j]) {
d1 = d0 + ed[p].len; q.push(i_i(d1, j));
}
}
}
}
re(i, n) if ( ! del[i]) {
d0 = cs[i] + dist[i];
if (d0 < res) res = d0;
}
}
void solve()
{
int lf, rt; s = 0 ;
re3(i, 0 , lmt) {
lf = g[s] - i; rt = lf + lmt;
re(j, n) del[j] = g[j] < lf || g[j] > rt;
sol1();
}
}
void pri()
{
printf( " %d\n " , res);
}
int main()
{
init();
solve();
pri();
return 0 ;
}