下午居然没做出这题,我傻了。。。一直在用我不熟悉的网络流在搞
网上也有人用最小树形图做
/*
    题意:给出一个有向图,a传到b的代价为c,同一个环内的传输不用代价
           求从一个点传到所有点的最小代价
    先强连通缩点 找到入度为0的点作为原点
    然后用spfa更新即可  更新的规则是 if(dist[v]>g[u][v])dist[v]=g[u][v]
    方正最后每个点都被传到,究竟它被谁传过来的呢?
    肯定是被花费最小的那条边传过来的
    这样子一直更新下去肯定是最优值!
    两种实现,用spfa也行   更直接的两重循环找每个点的父边中的最小值
*/

#include
<cstdio>
#include
<cstring>
#include
<vector>
#include
<algorithm>
#include
<queue>
using namespace std;

const int MAXN = 50000;
const int INF = 1000000000;

struct Edge
{
    
int v,w;
    Edge 
*next;
}
edge[100000*2+10],*E[MAXN+10],*_E[MAXN+10],*pE;

struct Graph
{
    vector
<int>G[200];
    
int SCC,n;
    
int ord[MAXN+10],ID[MAXN+10];
    
int g[200][200];
    
int ind[200],dist[200],in[200];

    
void init(int nn)
    
{
        n
=nn;
        memset(E,
0,sizeof(E));
        memset(_E,
0,sizeof(_E));
        pE
=edge;
    }

    
void add(int u,int v,int w)
    
{
        pE
->v=v;
        pE
->w=w;
        pE
->next=E[u];
        E[u]
=pE++;

        pE
->v=u;
        pE
->w=w;
        pE
->next=_E[v];
        _E[v]
=pE++;
    }

    
void dfs1(int u)
    
{
        ID[u]
=1;
        
for(Edge *it=_E[u];it;it=it->next)
        
{
            
if(ID[it->v]==-1)dfs1(it->v);
        }

        ord[SCC
++]=u;
    }

    
void dfs2(int u)
    
{
        ID[u]
=SCC;
        
for(Edge *it=E[u];it;it=it->next)
            
if(ID[it->v]==-1)dfs2(it->v);
    }

    
void kosaraju()
    
{
        SCC
=0;
        memset(ID,
-1,sizeof(ID));
        
for(int i=0;i<n;i++)
            
if(ID[i]==-1)dfs1(i);
        SCC
=0;
        memset(ID,
-1,sizeof(ID));
        
for(int i=n-1;i>=0;i--)
            
if(ID[ord[i]]==-1)
            
{
                dfs2(ord[i]);
                SCC
++;
            }

    }

    
void build()
    
{
         
for(int i=0;i<SCC;i++)
            
for(int j=0;j<SCC;j++)
                g[i][j]
=INF;
        
for(int i=0;i<n;i++)
            
for(Edge *it=E[i];it;it=it->next)
            
{
                
if(ID[i]==ID[it->v])continue;
                
if(it->w<g[ID[i]][ID[it->v]])g[ID[i]][ID[it->v]]=it->w;
            }


        
for(int i=0;i<SCC;i++)G[i].clear();
        memset(ind,
0,sizeof(ind));
        
for(int i=0;i<SCC;i++)
            
for(int j=0;j<SCC;j++)
                
if(g[i][j]!=INF)
                
{
                    G[i].push_back(j);
                    ind[j]
++;
                }

    }

    
int cal2()//对每个点,在其邻接矩阵中找父边中的最小值
    {
        
int ans = 0;
        
for(int j=0;j<SCC;j++)
        
{
            
int Min=INF;
            
for(int i=0;i<SCC;i++)
                
if(Min>g[i][j])Min=g[i][j];
            
if(Min!=INF)ans+=Min;
        }
    
        
return ans;
    }

    
int cal1()
    
{
        
int s;
        
for(int i=0;i<SCC;i++)
        
{
            dist[i]
=INF;
            
if(ind[i]==0)s=i;
        }

        dist[s]
=0;
        memset(
in,0,sizeof(in));
        
in[s]=1;
        queue
<int>Q;
        Q.push(s);
        
while(!Q.empty())
        
{
            
int u=Q.front();Q.pop();
            
for(int i=0,size=G[u].size();i<size;i++)
            
{
                
int v=G[u][i];
                
if(dist[v]>g[u][v])
                
{
                    dist[v]
=g[u][v];
                    
if(in[v]==0)
                    
{
                        
in[v]=1;
                        Q.push(v);
                    }

                }

            }

        }

        
int ans = 0;
        
for(int i=0;i<SCC;i++)
        
{
            ans
+=dist[i];
        }

        
return ans;
    }

}
graph;
int main()
{
    
//freopen("in","r",stdin);
    int n,m;
    
while(~scanf("%d%d",&n,&m))
    
{
        graph.init(n);       
        
for(int i=0;i<m;i++)
        
{
            
int a,b,c;
            scanf(
"%d%d%d",&a,&b,&c);
            graph.add(a,b,c);
        }

        graph.kosaraju();
        graph.build();
        
//printf("%d\n",graph.cal1());
        printf("%d\n",graph.cal2());
    }

    
return 0;
}