Luogu4716【模板】最小树形图
题面:洛谷
解析
没啥好讲的,模板而已,算法也很好理解。
ps:博主终于把这个咕了n久的算法学了虽然过一段时间就会忘掉
代码
// luogu-judger-enable-o2
#include<cstdio>
#define N 105
#define M 10005
using namespace std;
const int INF=1e9;
int n,m,root,_in[N],pre[N],vis[N],id[N];
#define gc() getchar()
inline int In(){
char c=gc(); int x=0,ft=1;
for(;c<'0'||c>'9';c=gc()) if(c=='-') ft=-1;
for(;c>='0'&&c<='9';c=gc()) x=x*10+c-'0';
return x*ft;
}
int h[N],e_eot=0;
struct E{ int u,v,w; }e[M];
int Solve(){
int ans=0,cnt;
while(1){
for(int i=1;i<=n;++i) _in[i]=INF;
for(int i=1;i<=m;++i){
int u=e[i].u,v=e[i].v;
if(u!=v&&e[i].w<_in[v]) _in[v]=e[i].w,pre[v]=u;
}
for(int i=1;i<=n;++i) if(i!=root&&_in[i]==INF) return -1;
cnt=0; for(int i=1;i<=n;++i) vis[i]=id[i]=0;
for(int i=1;i<=n;++i){
if(i==root) continue;
ans+=_in[i]; int v=i;
while(vis[v]!=i&&!id[v]&&v!=root){
vis[v]=i; v=pre[v];
}
if(!id[v]&&v!=root){
id[v]=++cnt;
for(int u=pre[v];u!=v;u=pre[u]) id[u]=cnt;
}
}
if(cnt==0) break;
for(int i=1;i<=n;++i) if(!id[i]) id[i]=++cnt;
for(int i=1;i<=m;++i){
int u=e[i].u,v=e[i].v;
e[i].u=id[u]; e[i].v=id[v];
if(id[u]!=id[v]) e[i].w-=_in[v];
}
root=id[root]; n=cnt;
}
return ans;
}
int main(){
n=In(); m=In(); root=In();
for(int i=1;i<=m;++i) e[i]=(E){In(),In(),In()};
printf("%d
",Solve());
return 0;
}