2021.1.29
Link
Solution
很早之前做过的题……今天又考,还很脑瘫地做错了……但发现之前并没有完全理解,所以还是写一下
先考虑问题一,求最多能到多少个点。容易知道只要存在一条通路,就一定能到,且后面算费用的时候该点一定能被算到。所以直接从 1 开始 bfs,统计能到的点个数。
问题二。将能到的所有点和所有边建成新图 (G')。再在该新图上求最小生成树。和常规的生成树不同,该图的边存在有向边,这会影响图的连通性。即如果连了一条边 (u o v),(v) 对 (u) 并不是连通的,然而并查集并不能区分这种差异,这就会造成最后求出的生成树不连通的问题。我们需要对 Kruskal 进行改造,将排序时加入以终点高度为第一关键字降序排,长度为第二关键字升序排。考虑这样的正确性。如果当前正在处理终点高度为 (H) 的边的话,那么高度大于 (H) 的点一定已经处理好了,并且一定是和 (1) 连通的。把这条边加上后,构造出的生成树也一定连通。
#include<stdio.h>
#include<queue>
#include<algorithm>
using namespace std;
#define rint register int
#define ll long long
#define N 200007
#define M N*10
template<class T>
inline void read(T &x){
x=0;char c=getchar();T flag=1;
while(c<'0'||c>'9'){if(c=='-')flag=-1;c=getchar();}
while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-48;c=getchar();}
x*=flag;
}
int n,m,X[M],Y[M],ans1=0,fa[N],cnt=0,_cnt=0,head[N],_head[N];
ll dis[M],h[N],ans2=0;
bool vis[N];
struct E{
int next,to,rk;
ll dis;
}e[M],_e[M];
queue<int> Q;
inline bool Cmp(const E a,const E b){
if(h[a.to]!=h[b.to]) return h[a.to]>h[b.to];
return a.dis<b.dis;
}
inline int find(int x){
if(x==fa[x]) return x;
return fa[x]=find(fa[x]);
}
inline void add_(int id,int to,ll dis,int rk){
_e[++_cnt]=(E){_head[id],to,rk,dis};
_head[id]=_cnt;
}
inline void add(int id,int to,ll dis,int rk){
e[++cnt]=(E){head[id],to,rk,dis};
head[id]=cnt;
}
inline void bfs(){
Q.push(1);vis[1]=true;ans1++;
while(!Q.empty()){
int u=Q.front();Q.pop();
for(rint i=_head[u];i;i=_e[i].next){
int v=_e[i].to;
add(u,v,_e[i].dis,_e[i].rk);
if(!vis[v]){
vis[v]=true;ans1++;
Q.push(v);
}
}
}
}
int main(){
freopen("irrigation.in","r",stdin);
freopen("irrigation.out","w",stdout);
read(n);read(m);
for(rint i=1;i<=n;++i) read(h[i]),fa[i]=i;
for(rint i=1;i<=m;++i){
read(X[i]);read(Y[i]);read(dis[i]);
if(h[X[i]]>=h[Y[i]]) add_(X[i],Y[i],dis[i],i);
if(h[X[i]]<=h[Y[i]]) add_(Y[i],X[i],dis[i],i);
}
bfs();
sort(e+1,e+1+cnt,Cmp);
rint k,u,v;
for(rint i=1;i<=cnt;++i){
k=e[i].rk;
u=X[k],v=Y[k];
if((!vis[u])||(!vis[v])) continue;
u=find(u),v=find(v);
if(u==v) continue;
fa[u]=v;ans2+=dis[k];
}
printf("%d %lld",ans1,ans2);
}