题意:简单点说就是求把所有强连通分量连在一起所需的最小花费
解析:先把所有强连通分量求出来,再求不同连通分量连接起来的最小花费,最后把除0所在的连通分量所需的最小花费连接起来。
int node[N];//顶点集合
int instack[N];//标记是否在stack中
int stack[N];
int Belong[N];//各顶点属于哪个强连通分量
int DFN[N];//节点u搜索的序号(时间戳)
int LOW[N];//u或u的子树能够追溯到的最早的栈中节点的序号(时间戳)
int n, m;//n:点的个数;m:边的条数
int cnt_edge;//边的计数器
int Index;//序号(时间戳)
int top;
int Bcnt;//有多少个强连通分量
//china no.1
#include <vector>
#include <iostream>
#include <string>
#include <map>
#include <stack>
#include <cstring>
#include <queue>
#include <list>
#include <stdio.h>
#include <set>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <iomanip>
#include <cctype>
#include <sstream>
#include <functional>
#include <stdlib.h>
#include <time.h>
#include <bitset>
using namespace std;
#define pi acos(-1)
#define endl '\n'
#define srand() srand(time(0));
#define me(x) memset(x,0,sizeof(x));
#define foreach(it,a) for(__typeof((a).begin()) it=(a).begin();it!=(a).end();it++)
#define close() ios::sync_with_stdio(0); cin.tie(0);
#define FOR(x,n,i) for(int i=x;i<=n;i++)
#define FOr(x,n,i) for(int i=x;i<n;i++)
#define W while
#define sgn(x) ((x) < 0 ? -1 : (x) > 0)
#define bug printf("***********\n");
typedef long long LL;
const int INF=0x3f3f3f3f;
const LL LINF=0x3f3f3f3f3f3f3f3fLL;
const int dx[]={-1,0,1,0,1,-1,-1,1};
const int dy[]={0,1,0,-1,-1,1,-1,1};
const int maxn=1e3+10;
const int maxx=2e5+100;
const double EPS=1e-7;
const int MOD=10000007;
template<class T>inline T min(T a,T b,T c) { return min(min(a,b),c);}
template<class T>inline T max(T a,T b,T c) { return max(max(a,b),c);}
template<class T>inline T min(T a,T b,T c,T d) { return min(min(a,b),min(c,d));}
template<class T>inline T max(T a,T b,T c,T d) { return max(max(a,b),max(c,d));}
int vis[maxx],dfn[maxx],low[maxx],bel[maxx],num[maxx],res,pre[maxx],a[maxx];
int cont=1,n,m;
struct node
{
int u,v,w;
}s[maxx];
vector<int>G[maxx],G_new[maxx];
queue<int>Q;
stack<int>S;
vector<node>g[maxx];
void dfs(int x)
{
dfn[x]=low[x]=cont++;
S.push(x);vis[x]=1;
int len=G[x].size();
for(int i=0; i<len; i++)
if(!vis[G[x][i]])
{
dfs(G[x][i]);
low[x]=min(low[x],low[G[x][i]]);
}
else if(vis[G[x][i]]==1)
low[x]=min(low[x],dfn[G[x][i]]);
if(dfn[x]==low[x])
{
res++;
while(1)
{
int t=S.top();
S.pop();
vis[t]=2; //访问完成
bel[t]=res;
if(x==t)break;
}
// if(res>1)ans++;
}
}
void init()
{
me(pre);me(vis);(low);me(bel);me(dfn);me(num);
for(int i=1;i<=n;i++)
{
G[i].clear();
pre[i]=INF;
g[i].clear();
}
me(s);
memset(a,INF,sizeof(a));
res=0;cont=1;
}
void solve()
{
while(~scanf("%d%d",&n,&m))
{
//close();
init();
for(int i=1;i<=m;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
x++;y++;
s[i].u=x;s[i].v=y;s[i].w=z;
G[x].push_back(y);
}
for(int i=1;i<=n;i++)
if(!vis[i]) dfs(i);
for(int i=1;i<=m;i++)
{
if(bel[s[i].u]!=bel[s[i].v])
a[bel[s[i].v]]=min(a[bel[s[i].v]],s[i].w);
}
int ans=0;
// cout<<res<<endl;
for(int i=1;i<=res;i++)
{
// cout<<a[i]<<endl;
if(a[i]!=INF) ans+=a[i];
}
cout<<ans<<endl;
}
}
int main()
{
// int t;
//t=1;
// close();
// cin>>t;
//for(int cas=1;cas<=t;cas++)
solve();
}
算入度:
for(int i=1; i<=n; i++) { int len=G[i].size(); for(int j=0; j<len; j++) if(bel[i]!=bel[G[i][j]]) in[bel[G[i][j]]]++; }