强连通分量板子 hdu 3072

本文介绍了一种算法,用于求解将图中所有强连通分量通过边连接起来所需的最小总花费。首先利用DFS求出所有强连通分量,然后计算不同分量间连接的最小花费。

 传送门

题意:简单点说就是求把所有强连通分量连在一起所需的最小花费

 解析:先把所有强连通分量求出来,再求不同连通分量连接起来的最小花费,最后把除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]]]++;
}




基于模拟退火的计算器 在线运行 访问run.bcjh.xyz。 先展示下效果 https://pan.quark.cn/s/cc95c98c3760 参见此仓库。 使用方法(本地安装包) 前往Releases · hjenryin/BCJH-Metropolis下载最新 ,解压后输入游戏内校验码即可使用。 配置厨具 已在2.0.0弃用。 直接使用白菜菊花代码,保留高级厨具,新手池厨具可变。 更改迭代次数 如有需要,可以更改 中39行的数字来设置迭代次数。 本地编译 如果在windows平台,需要使用MSBuild编译,并将 改为ANSI编码。 如有条件,强烈建议这种本地运行(运行可加速、可多次重复)。 在 下运行 ,是游戏中的白菜菊花校验码。 编译、运行: - 在根目录新建 文件夹并 至build - - 使用 (linux) 或 (windows) 运行。 最后在命令行就可以得到输出结果了! (注意顺序)(得到厨师-技法,表示对应新手池厨具) 注:linux下不支持多任务选择 云端编译已在2.0.0弃用。 局限性 已知的问题: - 无法得到最优解! 只能得到一个比较好的解,有助于开阔思路。 - 无法选择菜品数量(默认拉满)。 可能有一定门槛。 (这可能有助于防止这类辅助工具的滥用导致分数膨胀? )(你问我为什么不用其他语言写? python一个晚上就写好了,结果因为有涉及json读写很多类型没法推断,jit用不了,算这个太慢了,所以就用c++写了) 工作原理 采用两层模拟退火来最大化总能量。 第一层为三个厨师,其能量用第二层模拟退火来估计。 也就是说,这套方法理论上也能算厨神(只要能够在非常快的时间内,算出一个厨神面板的得分),但是加上厨神的食材限制工作量有点大……以后再说吧。 (...
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值