大意:在一个联通分量里面的边权值忽略不计,求缩点后的所有联通分量链接在一起的最小权值和。
思路:必然先缩点,最后得到的图为DAG,然后就是统计权值,对于那么到达当前的缩点可能有多个入度,所以选择最小的即可。最后避开起始点的dis[star] == inf.累加即可。
#include<map> #include<queue> #include<cmath> #include<cstdio> #include<stack> #include<iostream> #include<cstring> #include<algorithm> #define LL int #define inf 0x3f3f3f3f #define eps 1e-8 #include<vector> #define ls l,mid,rt<<1 #define rs mid+1,r,rt<<1|1 #define LL __int64 using namespace std; const int nv = 50100; const int ne = 101000; struct node{ int to,w,next; }q[ne<<1]; const int Ma = nv; int head[ne<<1],dfn[Ma],num[Ma],du[Ma],stk[Ma],vis[Ma],low[Ma]; int cnt,top,tim,scc,dis[Ma]; LL ans; void Add(int a,int b,int c){ q[cnt].to = b; q[cnt].w = c; q[cnt].next = head[a]; head[a] = cnt++; } void init(){ ans = scc = cnt = top = 0; tim = 1; memset(head,-1,sizeof(head)); memset(dfn,0,sizeof(dfn)); memset(num,0,sizeof(num)); memset(vis,0,sizeof(vis)); memset(low,0,sizeof(low)); } void Tarjan(int u){ low[u] = dfn[u] = tim++; vis[u] = 1; stk[top++] = u; for(int i = head[u]; ~i ; i = q[i].next){ int v = q[i].to; if(!dfn[v]){ Tarjan(v); low[u] = min(low[u],low[v]); } else if(vis[v]) low[u] = min(low[u],dfn[v]); } if(low[u] == dfn[u]){ scc++; while(top > 0&&stk[top] != u){ top --; vis[stk[top] ] = 0; num[stk[top] ] = scc; } } } int main(){ int n,m,i,j,k,a,b,c,cla; while(~scanf("%d%d",&n,&m)){ init(); for(i = 0;i <m;++ i){ scanf("%d%d%d",&a,&b,&c); Add(a,b,c); } for(i = 0;i < n;++ i) if(!dfn[i]) Tarjan(i); memset(dis,inf,sizeof(dis)); for(i = 0;i < n;++ i) for(j = head[i];~j;j=q[j].next){ int v = q[j].to; if(num[i] != num[v]){ dis[ num[v] ] = min(dis[num[v] ],q[j].w); } } for(i = 1;i <= scc;++ i){ if(dis[i]!=inf) ans+=dis[i]; } printf("%I64d\n",ans); } return 0; }
时间: 2024-11-06 03:51:27