标签:
Input
Output
Sample Input
3 3 0 1 100 1 2 50 0 2 100 3 3 0 1 100 1 2 50 2 1 100 2 2 0 1 50 0 1 100
Sample Output
150 100 50
题意:简单点说就是求把所有强连通分量连在一起所需的最小花费
解析:先把所有强连通分量求出来,再求不同连通分量连接起来的最小花费,最后把除0所在的连通分量所需的最小花费连接起来,
代码
#include<cstdio> #include<cstring> #include<string> #include<iostream> #include<sstream> #include<algorithm> #include<utility> #include<vector> #include<set> #include<map> #include<queue> #include<cmath> #include<iterator> #include<stack> using namespace std; const int INF=1e9+7; const int eps=0.0000001; typedef __int64 LL; const int maxn=50005; const int maxm=100005; int N,M,ans,id; int dfn[maxn],low[maxn],cost[maxn],resign[maxn]; vector<int> G[maxn]; stack<int> KK; bool inq[maxn]; struct edge { int u,v,w; edge(int u=0,int v=0,int w=0):u(u),v(v),w(w){} }E[maxm]; void init() { ans=id=0; while(!KK.empty()) KK.pop(); for(int i=0;i<=N;i++) { dfn[i]=low[i]=0; resign[i]=0; cost[i]=INF; G[i].clear(); inq[i]=false; } } void Tarjan(int x) { dfn[x]=low[x]=++id; inq[x]=true; KK.push(x); int t,Size=G[x].size(); for(int i=0;i<Size;i++) { t=G[x][i]; if(!dfn[t]) { Tarjan(t); low[x]=min(low[x],low[t]); } else if(inq[t]) low[x]=min(low[x],dfn[t]); } //前面都差不多 if(dfn[x]==low[x]) { ans++; do { t=KK.top(); KK.pop(); inq[t]=false; resign[t]=ans; //这个地方,标记连通分量 }while(t!=x); } return; } int main() { while(scanf("%d%d",&N,&M)!=EOF) { init(); int u,v,w; for(int i=1;i<=M;i++) { scanf("%d%d%d",&u,&v,&w); E[i]=edge(u,v,w); G[u].push_back(v); //有向图 } for(int i=0;i<N;i++) if(!dfn[i]) Tarjan(i); for(int i=1;i<=M;i++) { edge& e=E[i]; int u=e.u,v=e.v,w=e.w; int x=resign[u],y=resign[v]; //连通分量繁荣编号 if(x!=y) cost[y]=min(cost[y],w); //更新值 } int sum=0; for(int i=1;i<=ans;i++) { if(i==resign[0]||cost[i]==INF) continue;//跟0是统一连通分量的不管 sum+=cost[i]; } printf("%d\n",sum); } return 0; }
Hdu3072-Intelligence System(强连通求最小值)
标签:
原文地址:http://www.cnblogs.com/wust-ouyangli/p/5722496.html