http://acm.hdu.edu.cn/showproblem.php?pid=3072
这题针不戳啊,环上的边全部免费,那么就是强连通分量缩点,接下来就是个无环有向图,求最小树形图,那么就直接把缩点后的点每条最小的入边选出来就行了,而且题目还保证有解
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxl=1e5+10;
const int inf=1e9+10;
int n,m,ind,ff,top;ll ans;
int dfn[maxl],low[maxl],f[maxl],s[maxl],ine[maxl];
bool in[maxl];
struct ed{int u,v,l;} edg[maxl];
vector<ed> e[maxl];
inline void prework()
{
for(int i=1;i<=n;i++)
dfn[i]=low[i]=f[i]=0,in[i]=false,e[i].clear();
ind=ff=top=0;
for(int i=1;i<=m;i++)
{
int u,v,l;
scanf("%d%d%d",&u,&v,&l);++u;++v;
e[u].push_back(ed{u,v,l});
edg[i]=ed{u,v,l};
}
}
inline void tarjan(int u)
{
s[++top]=u;in[u]=true;
dfn[u]=low[u]=++ind;
for(ed ee:e[u])
{
int v=ee.v;
if(!dfn[v])
{
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(in[v])
low[u]=min(dfn[v],low[u]);
}
if(dfn[u]==low[u])
{
ff++;int v;
do
v=s[top--],f[v]=ff,in[v]=false;
while(v!=u);
}
}
inline void mainwork()
{
tarjan(1);
for(int i=1;i<=ff;i++)
ine[i]=inf;
for(int i=1;i<=m;i++)
{
int u=f[edg[i].u],v=f[edg[i].v],l=edg[i].l;
if(u!=v)
ine[v]=min(ine[v],l);
}
ans=0;
for(int i=1;i<=ff;i++)
if(i!=f[1])
ans+=ine[i];
}
inline void print()
{
printf("%lld\n",ans);
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
prework();
mainwork();
print();
}
return 0;
}