CF:Problem 427C - Checkposts强连通Tarjan算法

这题昨晚做了,刚开始看题的时候没想出好法子,然后就看D题了,一看D题发现是后缀数组,然后就把模板改了点就交了上去……不幸的是……WA了,然后重新看题,果然题目看漏了……不仅要用后缀数组和前缀数组求出公共子缀,还要是求最小的,而且在每个串里都不能重复的,这下就想了会不会了,然后看见大帝C过了,然后就重新回来看C了,看了会终于明天怎么做了。

C题意:给个图,然后每个点都有权值,求最小的花费及方案数;最小的花费是这样的:因为是建立一个岗哨,然后这个岗哨可以管哪些呢,可以管 i = j 的,或者可以从 i 出发到 j ,然后还可以从 j  出发回到 i 的,注意题目给出的是单身图,所以从 i 出发到 j ,不一定能从 j 回到 i 。

思路:根据题目要求可知:最小花费就是求出一些点,然后这些点的权值之和最小,并且这些点都能管住所有的点(即所有的点都能被自身或者被其他的点管着,不能漏了)。又因为要求出方案数,为什么有方案数这一说呢?因为如果两个点的权值相同,然后又互相连通,那么这就有两种方案了是吧!所以说到这里就可以知道用强连通做了!

每个强连通里取最小的值之和就是最小花费了,然后每个强连通里最小值的个数相乘当然就是方案数啦!!!因为每个最小树值的结点都可以建立岗哨嘛,然后都是连通的当然建立一个就行咯,方案数就是这样滴咯!

昨晚敲了一个小时,唉……在强连通里求方案的时候一直出错,只过了3个样列,然后一直改到比赛结束了还没得交!可惜了!刚才重新做直接就在Tarjan求强连通那do-while里面就可以直接求出最小花费和方案数了,昨天是在main函数里面做一直出错不知道为啥不行,其做法实质都是一样的啊,唉……写挫了昨晚

#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#define PI acos(-1.0)
#define mem(a,b) memset(a,b,sizeof(a))
#define sca(a) scanf("%d",&a)
#define sc(a,b) scanf("%d%d",&a,&b)
#define pri(a) printf("%d\n",a)
#define lson i<<1,l,mid
#define rson i<<1|1,mid+1,r
#define MM 400005
#define MN 100005
#define INF 1000000007
#define eps 1e-7
using namespace std;
typedef long long ll;
int n,m,cnt,tem,Count,DFN[MN],LOW[MN],vis[MN],suo[MN],q2[MN];
vector<int>q[MN];
int bb[MN];
ll sum,tmp=1;
void tarjan(int u)
{
    int j,v;
    DFN[u]=LOW[u]=++cnt;
    vis[u]=1;
    q2[++tem]=u;
    for(j=0; j<q[u].size(); j++)
    {
        v=q[u][j];
        if(!DFN[v])
        {
            tarjan(v);
            LOW[u]=min(LOW[u],LOW[v]);
        }
        else if(vis[v]&&DFN[v]<LOW[u])
            LOW[u]=DFN[v];
    }
    if(DFN[u]==LOW[u])
    {
        Count++;
        int x=0,y=INF;
        do
        {
            v=q2[tem--];
            vis[v]=0;
            suo[v]=Count;
            if(y>bb[v]) x=1,y=bb[v];
            else if(y==bb[v]) x++;
        }
        while(v!=u);
        sum+=y,tmp=tmp*x%INF;
    }
}
void solve()
{
    int v,i,j,kk=0;
    Count=cnt=tem=0;
    mem(DFN,0);
    for(i=1; i<=n; i++)
        if(!DFN[i]) tarjan(i);
    cout<<sum<<‘ ‘<<tmp<<endl;
}
int main()
{
    cin>>n;
    int u,v;
    for(int i=1;i<=n;i++) sca(bb[i]);
    sca(m);
    for(int i=0;i<m;i++)
    {
        sc(u,v);
        q[u].push_back(v);
    }
    solve();
    return 0;
}

CF:Problem 427C - Checkposts强连通Tarjan算法,布布扣,bubuko.com

时间: 2024-12-29 17:10:06

CF:Problem 427C - Checkposts强连通Tarjan算法的相关文章

CF:Problem 427C - Checkposts强连通 Tarjan算法

tarjan算法第一题 喷我一脸....把手写栈的类型开成了BOOL,一直在找错... #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define maxn 100005 const int MOD=1000000007; using namespace std; struct node { int to,next; }edge[maxn*3]; int

CF:Problem 427C - Checkposts良好的沟通 Tarjan算法

tarjan算法的第一个问题 喷我的脸....手写叠式开成BOOL,我一直在找错了... #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define maxn 100005 const int MOD=1000000007; using namespace std; struct node { int to,next; }edge[maxn*3]; int

图的连通性:强连通-Tarjan算法

不早了,先上个模板,做些题再来分析一下: 强连通Tarjan算法+前向星 模板如下: const int MAXN=110; const int MAXM=10010; struct edge { int to,next; }; edge E[MAXN]; int head[MAXN],Ecou; int Stack[MAXN],top; int Belong[MAXN],lfcou; int Index; int DFN[MAXN],LOW[MAXN]; bool inStack[MAXN];

ZOJ Problem - 2588 Burning Bridges tarjan算法求割边

题意:求无向图的割边. 思路:tarjan算法求割边,访问到一个点,如果这个点的low值比它的dfn值大,它就是割边,直接ans++(之所以可以直接ans++,是因为他与割点不同,每条边只访问了一遍). 需要注意的就是此处有多重边,题目中要求输出确定的不能被删除的边,而多重边的保留不是可以确定的,所以多重边都是不可以被保留的,我们可以在邻接表做一个flag的标记,判断他是不是多重边. 注意建图的时候数组应该是m × 2,因为这里是无向边,当心RE! 注意输出的时候编号是必须要拍好序再输出. 还有

求图的强连通分量--tarjan算法

一:tarjan算法详解 ?思想: ? ?做一遍DFS,用dfn[i]表示编号为i的节点在DFS过程中的访问序号(也可以叫做开始时间)用low[i]表示i节点DFS过程中i的下方节点所能到达的开始时间最早的节点的开始时间.(也就是之后的深搜所能到达的最小开始时间)初始时dfn[i]=low[i] ? ?在DFS过程中会形成一搜索树.在搜索树上越先遍历到的节点,显然dfn的值就越小. ? ?DFS过程中,碰到哪个节点,就将哪个节点入栈.栈中节点只有在其所属的强连通分量已经全部求出时,才会出栈. ?

poj 2186 Popular Cows 【强连通分量Tarjan算法 + 树问题】

题目地址:http://poj.org/problem?id=2186 Popular Cows Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 27496   Accepted: 11059 Description Every cow's dream is to become the most popular cow in the herd. In a herd of N (1 <= N <= 10,000) cows

HDU 1269 强连通分量tarjan算法

迷宫城堡 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 6655    Accepted Submission(s): 2973 Problem Description 为了训练小希的方向感,Gardon建立了一座大城堡,里面有N个房间(N<=10000)和M条通道(M<=100000),每个通道都是单向的,就是说若称某通道连通了A房

图之强连通、强连通图、强连通分量 Tarjan算法

强连通分量 简介 在阅读下列内容之前,请务必了解图论基础部分. 强连通的定义是:有向图 G 强连通是指,G 中任意两个结点连通. 强连通分量(Strongly Connected Components,SCC)的定义是:极大的强连通子图. 这里想要介绍的是如何来求强连通分量. Tarjan 算法 Robert E. Tarjan (1948~) 美国人. Tarjan 发明了很多算法结构.光 Tarjan 算法就有很多,比如求各种联通分量的 Tarjan 算法,求 LCA(Lowest Comm

【强连通分量】tarjan算法及kosaraju算法+例题

阅读前请确保自己知道强连通分量是什么,本文不做赘述. Tarjan算法 一.算法简介 Tarjan算法是一种由Robert Tarjan提出的求有向图强连通分量的时间复杂度为O(n)的算法. 首先我们要知道两个概念:时间戳(DFN),节点能追溯到的最早的栈中节点的时间戳(LOW).顾名思义,DFN就是在搜索中某一节点被遍历到的次序号(dfs_num),LOW就是某一节点在栈中能追溯到的最早的父亲节点的搜索次序号. Tarjan算法是基于深度优先搜索的算法.在搜索过程中把没有Tarjan过的点入栈