【tarjan缩点】hdu 3072

本文详细阐述了一种通过先压缩点、查找无入边点、然后找到权重最小边的方法来解决图中环路问题的算法。讨论了使用vector和stack的数据结构在实现过程中的作用,强调了在可能存在重复边的情况下正确处理的重要性。通过实例演示了如何在给定的图结构中应用此算法,并最终输出了去除环路后的最小权重总和。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这题要先缩点在找没有入边的点,再找权值最小的边,注意:可能有重边,看sample3就知道!

用vector和stack的缘故,比较慢500+ms

#include <list> #include <map> #include <set> #include <queue> #include <string> #include <deque> #include <stack> #include <algorithm> #include <iostream> #include <iomanip> #include <cstdio> #include <math.h> #include <cstdlib> #include <limits.h> #include <time.h> #include <string.h> using namespace std;

#define LL long long #define PI acos(-1.0) #define FRE freopen("a.txt","r",stdin) #define MAX INT_MAX #define MIN INT_MIN #define eps 1e-10 #define MOD 1000000007 #define N  50005 int min(int a,int b){return a<b?a:b;} struct node{     int t;     int w; }; int n,m; vector<node> v[N]; stack<int> s; bool vis[N]; bool Instack[N]; int low[N],dfn[N]; int belong[N]; int step,t; int cost[N];

void init(){     int i;     for(i=0;i<=n;i++){         v[i].clear();         vis[i]=0;         low[i]=dfn[i]=0;         Instack[i]=0;         belong[i]=0;         cost[i]=MAX;     }     while(!s.empty())s.pop();     t=0;     step=0; } void tarjan(int u){     vis[u]=1;     step++;     s.push(u);     Instack[u]=1;     low[u]=dfn[u]=step;     int i,j;     for(i=0;i<v[u].size();i++){         int x=v[u][i].t;         if(!vis[x]){             tarjan(x);             low[u]=min(low[u],low[x]);         }         else{             if(Instack[x])             low[u]=min(low[u],dfn[x]);         }     }     if(low[u]==dfn[u]){         t++;         while(1){             int x=s.top();             s.pop();             belong[x]=t; ////             Instack[x]=0;             if(x==u)break;         }     } } void gao(){     int i,j;     for(i=0;i<n;i++)     if(!vis[i])     tarjan(i);

    for(i=0;i<n;i++){         int x=belong[i];         for(j=0;j<v[i].size();j++){             int y=belong[v[i][j].t];             if(x==y)continue;             else{                 cost[y]=min(cost[y],v[i][j].w);             }         }     }     int ans=0;     for(i=0;i<n;i++){         if(cost[i]!=MAX)         ans+=cost[i];     }     printf("%d\n",ans); } int main(){     while(scanf("%d%d",&n,&m)!=EOF){         int i,j;         init();         while(m--){             int a,b,c;             scanf("%d%d%d",&a,&b,&c);             node tmp;             tmp.t=b;             tmp.w=c;             v[a].push_back(tmp);         }         gao();     }     return 0; }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值