【题解】Luogu P2573 [SCOI2012] 滑雪 最小生成树
并查集写错少find了导致一直MLE。。。
dfs+kruskal
因为时间胶囊无限,所以相当于回溯回祖先节点再向下dfs
先dfs一遍看最多能滑多少点,能滑到的点连边
用这些新的边跑最小生成树,排序的时候先按高度从大到小再按边权从小到大
code
1 #include<bits/stdc++.h> 2 using namespace std; 3 namespace gengyf{ 4 const int maxn=1e5+5; 5 #define int long long 6 inline int read(){ 7 int x=0,f=1;char s=getchar(); 8 while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();} 9 while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();} 10 return f*x; 11 } 12 int n,m,h[maxn],sum=1,tot,ans; 13 struct Edge{ 14 int u,v,w; 15 }E[maxn*20]; 16 struct edge{ 17 int nxt,to,w; 18 }e[maxn*20]; 19 int head[maxn],cnt,fa[maxn]; 20 bool vis[maxn]; 21 inline void add(int from,int to,int w){ 22 e[++cnt].to=to;e[cnt].w=w;e[cnt].nxt=head[from];head[from]=cnt; 23 } 24 void dfs(int x){ 25 for(int i=head[x];i;i=e[i].nxt){ 26 int to=e[i].to; 27 E[++tot].u=x;E[tot].v=to;E[tot].w=e[i].w; 28 if(!vis[to]){ 29 vis[to]=1;sum++;dfs(to); 30 } 31 } 32 } 33 bool cmp(Edge a,Edge b){ 34 return h[a.v]==h[b.v]?a.w<b.w:h[a.v]>h[b.v]; 35 } 36 int find(int x){ 37 return x==fa[x]?x:fa[x]=find(fa[x]); 38 } 39 int main(){ 40 n=read();m=read(); 41 for(int i=1;i<=n;i++){ 42 h[i]=read();fa[i]=i; 43 } 44 for(int i=1;i<=m;i++){ 45 int u,v,w; 46 u=read();v=read();w=read(); 47 if(h[u]==h[v]){ 48 add(u,v,w);add(v,u,w); 49 } 50 else if(h[u]>h[v])add(u,v,w); 51 else add(v,u,w); 52 } 53 vis[1]=1;dfs(1); 54 sort(E+1,E+1+tot,cmp); 55 int k=0; 56 for(int i=1;i<=tot;i++){ 57 int u=find(E[i].u),v=find(E[i].v); 58 if(u!=v){ 59 fa[u]=v; 60 ans+=E[i].w;k++; 61 } 62 if(k==sum-1)break; 63 } 64 printf("%lld %lld",sum,ans); 65 return 0; 66 } 67 /* 68 acquisition 得到 69 adapt 适应 70 adequate 足够的 71 */ 72 } 73 signed main(){ 74 gengyf::main(); 75 return 0; 76 }
忽略后面的单词(雾