由于环内传递不需要费用,求最小树形图就变的很简单,在缩点过的图中取出每个点的最小入边求和即可。
////////////////////////////// /* HDU 3072 Intelligence System 强连通分量 重构图 最小树形图 */ ///////////////////////////// #include<iostream> #include<vector> using namespace std; #define MY_MAX 100004 #define MAX_BRANCHES 200 #define INF 200000000 bool visited[MY_MAX], instack[MY_MAX]; int stack[MY_MAX], top; int N, M; vector<int> graph[MY_MAX]; vector<int> g[MY_MAX];//rebuilded int dfn[MY_MAX], low[MY_MAX]; int color[MY_MAX]; int INDEX, num; int fee[MAX_BRANCHES][MAX_BRANCHES]; int used[MAX_BRANCHES]; struct edge { int x,y,fee; }; edge e[MY_MAX]; int min(int x,int y) { if (x<y) return x; else return y; } void tarjan(int u){ int v; dfn[u] = low[u] = INDEX++; stack[++top] = u; instack[u] = true; visited[u] = true; for(size_t i=0; i<graph[u].size(); ++i){ v = graph[u][i]; if(!visited[v]){ tarjan(v); low[u] = min(low[u], low[v]); } else if(instack[v]) low[u] = min(low[u], dfn[v]); } if(dfn[u] == low[u]){ ++num; color[u]=num; do{ v = stack[top--]; color[v]=num; instack[v] = false; }while(v != u); } } int main() { int n,m,i,j,x,y,z; int blocks,block_color,ans; while(cin>>n>>m) { for(i=0;i<=n;i++) graph[i].clear(); for(i=1;i<=m;i++) { scanf("%d%d%d",&x,&y,&z); e[i].x=x;e[i].y=y;e[i].fee=z; graph[x].push_back(y); } /////////////////////////////////// //init.... top=0;num=0;INDEX=1; memset(visited,0,sizeof(visited)); memset(instack,0,sizeof(instack)); ////////////////////////////////// //calc color by tarjan for(i=0;i<n;i++) if (!visited[i]) tarjan(i); ////////////////////////////////// //rebuild a map for(i=1;i<=num;i++) for(j=1;j<=num;j++) fee[i][j]=INF; for(i=1;i<=m;i++) if (color[e[i].x]!=color[e[i].y]) //不能自己指向自己 fee[color[e[i].x]][color[e[i].y]]=min(fee[color[e[i].x]][color[e[i].y]],e[i].fee); /////////////////////////////////// ans=0; memset(used,0,sizeof(used)); used[color[0]]=true; for(i=1;i<=num-1;i++) { int temp_fee,tempk,k,j; temp_fee=INF; for(j=1;j<=num;j++) for(k=1;k<=num;k++) { if ( (!used[k])&&fee[j][k]<temp_fee ) { temp_fee=fee[j][k]; tempk=k; } } used[tempk]=true; ans+=temp_fee; } printf("%d/n",ans); } }