先缩点 然后选择权制 要小心可能会超过int 勉强卡着时限过了
t
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<vector>
#include<algorithm>
using namespace std;
#define maxn 50010
#define inf 100005555
int n;//顶点数
struct edge
{
int to,value;
};
vector<int>rg[maxn];
vector<edge>g[maxn];
vector<int>vs; //后序遍历顺序的顶点列表
bool vis[maxn];
int scin[maxn],scout[maxn];
int cmp[maxn]; //所属强联通分量的拓扑序
int value[maxn];
void add(int from,int to,int value)
{
g[from].push_back((edge){to,value});
rg[to].push_back(from);
}
void dfs(int v)
{
vis[v]=1;
for(int i=0;i<g[v].size();++i)
{
if(!vis[g[v][i].to])dfs(g[v][i].to);
}
vs.push_back(v);
}
void rdfs(int v,int k)
{
vis[v]=1;
cmp[v]=k;
for(int i=0;i<rg[v].size();++i)
{
if(!vis[rg[v][i]]){rdfs(rg[v][i],k);}
}
}
int scc()
{
memset(vis,0,sizeof vis);
memset(cmp,0,sizeof cmp);
vs.clear();
for(int i=0;i<n;i++)
{
if(!vis[i])dfs(i);
}
memset(vis,0,sizeof vis);
int k=0;
for(int i=vs.size()-1;i>=0;i--)
{
if(!vis[vs[i]])rdfs(vs[i],k++);
}
return k;
}
int main()
{
int m,a,b,c;
while(~scanf("%d%d",&n,&m))
{
if(n==0&&m==0)break;
// memset(scin,0,sizeof scin);
// memset(scout,0,sizeof scout);
for(int i=0;i<n;++i)
{value[i]=inf;}
for(int i=0;i<m;++i)
{
scanf("%d%d%d",&a,&b,&c);
add(a,b,c);
}
int sc=scc();
for(int i=0;i<n;++i)
{
for(int j=0;j<g[i].size();++j)
{
if(cmp[i]!=cmp[g[i][j].to])
{
// scin[cmp[g[i][j]]]++;
if(value[cmp[g[i][j].to]]>g[i][j].value)
{
// printf("rudian:%d\n",g[i][j].to);
value[cmp[g[i][j].to]]=g[i][j].value;
}
}
}
}
value[0]=0;
long long num2=0;
for(int i=0;i<sc;++i)
{
num2+=value[i];
// if(scout[i]==0)num2++;
}
printf("%lld\n",num2);
for(int i=0;i<=n;++i){g[i].clear();rg[i].clear();}
}
}
t