大意:在一个联通分量里面的边权值忽略不计,求缩点后的所有联通分量链接在一起的最小权值和。
思路:必然先缩点,最后得到的图为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;
}