\(problem\)
这题就是 搜索 + 最小生成树?
反正就是这样的
- 求从1开始能最到几个地方。
2.最短长度 即最小生成树。
我的做法是 先前向星存图 存好之后遍历 弄好第一个问 顺便处理好第二个问。
可以搜索 遍历出来 能到几个点。 然后顺便重新存图 因为有些路径就在这时候显得一点没用了。
然后跑\(kruskal\) 求最短距离? 没了。
关于排序的话 有一点 要从高到低排 高度相同的 取最小(最小生成树)
所以的话呢
我们需要一个cmp
bool cmp(E x , E y) { return h[x.v] == h[y.v] ? x.w < y.w : h[x.v] > h[y.v] ; }
然而这样的话 就可以达到排序的目的 也就是保证拓展的点最多
关于前向星存图 注意的是 高度相等需要建双向边。
数组开两倍(大雾
#include
using namespace std ;
//#define int long long
typedef long long LL ;
inline int rd() { int x = 0 ; int f = 1 ; register char c ;
#define gc c = getchar()
while(isspace(gc)) ;
if(c == '-') f = -1 , gc ;
while(x = (x<<1) + (x<<3) + (c&15) , isdigit(gc)) ;
return x * f ;
#undef gc
}
int n , m ;
const int inf = INT_MAX >> 1 ;
const int N = 100000 + 5 ;
int h[N] ;
const int M = 1000000 + 5 ;
struct node { int to ; int val ; int nxt ; } Edge[M << 1] ;
int cnt(0) ;
int head[N] ;
struct E { int u ; int v ; int w ; } edge[M << 1] ;
bool cmp(E x , E y) { return h[x.v] == h[y.v] ? x.w < y.w : h[x.v] > h[y.v] ; }
inline void Add(int u , int v , int w) {
Edge[++ cnt].to = v , Edge[cnt].val = w , Edge[cnt].nxt = head[u] ;
head[u] = cnt ;
}
int fa[N] ;
inline int find (int x) { return x == fa[x] ? x : fa[x] = find (fa[x]) ; }
inline void merge(int x , int y) { fa[x] = y ; }
bool vis[N] ;
int num(0) , sum(1) ;
LL ans(0) ;
inline void Dfs(int x) {
for(register int i = head[x] ; i ; i = Edge[i].nxt) {
edge[++ num].u = x ; edge[num].v = Edge[i].to ; edge[num].w = Edge[i].val ;
if(!vis[Edge[i].to]) vis[Edge[i].to] = 1 , ++ sum , Dfs(Edge[i].to) ;
}
}
inline void kruskal() {
sort(edge + 1 , edge + num + 1 , cmp) ;
for(register int i=1;i<=num;i++) {
int fx = find(edge[i].u) , fy = find(edge[i].v) ;
if(fx == fy) continue ;
merge(fx , fy) ; ans += edge[i].w ;
}
return ;
}
signed main() {
n = rd() , m = rd() ;
for(register int i=1;i<=n;i++) fa[i] = i ;
for(register int i=1;i<=n;i++) h[i] = rd() ;
for(register int i=1;i<=m;i++) {
int u = rd() , v = rd() , w = rd() ;
if(h[u] >= h[v]) Add(u , v , w) ;
if(h[u] <= h[v]) Add(v , u , w) ;
}
vis[1] = 1 , Dfs(1) ;
kruskal() ;
cout << sum << ' ' << ans << endl ;
return 0 ;
}