【題目大意】給乙個包含n個點,m條邊的無向連通圖。從頂點1出發,往其餘所有點分別走一次並返回。
往某乙個點走時,選擇總長度最短的路徑走。若有多條長度最短的路徑,則選擇經過的頂點序列字典序最小的那條路徑(如路徑a為1,32,11,路徑b為1,3,2,11,路徑b字典序較小。注意是序列的字典序的最小,而非路徑中節點編號相連的字串字典序最小)。到達該點後按原路返回,然後往其他點走,直到所有點都走過。
可以知道,經過的邊會構成一棵最短路徑樹。請問,在這棵最短路徑樹上,最長的包含k個點的簡單路徑長度為多長?以及長度為該最長長度的不同簡單路徑有多少條?
這裡的簡單路徑是指:對於乙個點最多隻經過一次的路徑。不同路徑是指路徑兩端端點至少有乙個不同,點a到點b的路徑和點b到點a視為同一條路徑。
【題解】今天太晚了以後再寫
#include#include#include#include#define fo(i,a,b) for (int i = a;i <= b;i ++)
using namespace std;
const int maxn = 30005;
int n,m,k,ans,sum,root,size,cnt;
int s[maxn],f[maxn];
struct graph
old,new;
struct t
return l;
}};void graph::insert(int x,int y,int z)
void graph::spfa()}}
bz[x] = 0;
} fo(i,2,n) }
void graph::findroot(int x,int last)
f[x] = max(f[x],size-s[x]);
if (f[x] < f[root]) root = x;
}t tank[maxn];
inline void update(int x,int _l,int time)
else
if (_l == tank[x].l)
tank[x].n ++;
} else
tank[x].t = time;
}inline void upd_ans(int l,int cnt)
else
if (l == ans) sum += cnt;
}void graph::collect(int x,int dep,int len,int last,int time)
void graph::dfs(int x,int dep,int len,int last,int time)
void graph::work(int x,int t)
flag[x] = 1;
for (int i = a[x];i;i = c[i])
if (!flag[b[i]]) }
int main()
old.spfa();
f[0] = size = n;
new.findroot(1,root = 0);
new.work(root,cnt = 1);
printf("%d %d\n",ans,sum);
return 0;
}
FJOI2014最短路徑樹問題
給乙個包含n個點,m條邊的無向連通圖。從頂點1出發,往其餘所有點分別走一次並返回。往某乙個點走時,選擇總長度最短的路徑走。若有多條長度最短的路徑,則選擇經過的頂點序列字典序最小的那條路徑 如路徑a為1,32,11,路徑b為1,3,2,11,路徑b字典序較小。注意是序列的字典序的最小,而非路徑中節點編...
FJOI2014 最短路徑樹問題
here 吐槽一下這個題,完全就是兩個裸題拼一起了,而且兩個板子之間毫無聯絡 首先我們造乙個保證字典序最小的最短路徑樹,怎麼保證字典序呢,先將你存的圖按字典序從小到大重新排個序再跑最短路就行了。之後就是 跑 dijkstra dfs 一遍重新建圖,如果 u 已經被訪問過,那麼邊 e 在最短路上的當且...
FJOI2014 最短路徑樹問題
這題已經在我的收藏夾裡吃了大半年的灰了 主要是因為他們有人把這題歸到了樹形dp裡面,然後我就傻乎乎地把它收藏了 首先,假設我們已經求出了這個 最短路徑樹 剩下的就是點分治的板子了。而這個 最短路徑樹 首先可以通過dijkstra跑出最短路徑dag,然後在dag上用bfs即可求出字典序最小的樹。總的來...