强连通缩点— HDU1827

  强连通缩点以后最终形成的是一棵树

  我们可以根据树的性质来看缩点以后的强连通分量图,就很好理解了

/*  gyt
       Live up to every day            */
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<vector>
#include<stack>
#include<cstring>
#include<queue>
#include<set>
#include<string>
#include<map>
#include <time.h>
#define PI acos(-1)
using namespace std;
typedef long long ll;
typedef double db;
const int maxn = 4000+10;
const ll maxm = 1e7;
const int modd = 10000007;
const int INF = 1<<30;
const db eps = 1e-9;
struct Edge{
    int u, v, next;
}e[maxn*4];
int n, m, cnt,scnt, tot;
stack<int>sta;
int dfn[maxn], low[maxn], vis[maxn], head[maxn];
int du[maxn], color[maxn];
int a[maxn], in[maxn];

void init() {
    memset(head, -1, sizeof(head));
    memset(dfn, 0, sizeof(dfn));
    memset(low, 0, sizeof(low));
    memset(vis, 0, sizeof(vis));
    memset(du, 0, sizeof(du));
    memset(color, 0, sizeof(color));
    for (int i=0; i<maxn; i++)  in[i]=INF;
    while(!sta.empty())  sta.pop();
    cnt=0;
    scnt=0;  tot=0;
}
void add(int u, int v) {
    e[cnt].v=v, e[cnt].next=head[u];
    head[u]=cnt++;
}
void Tarjan(int s) {
    int minn, t;
    dfn[s]=low[s]=++tot;
    vis[s]=2;
    sta.push(s);
    for (int i=head[s]; ~i; i=e[i].next) {
        int t=e[i].v;
        if (!dfn[t]) {
            Tarjan(t);
            low[s]=min(low[s], low[t]);
        } else {
            if (vis[t]==2) {
                low[s]=min(low[s], dfn[t]);
            }
        }
    }
    if (low[s]==dfn[s]) {
        scnt++;
        while(!sta.empty()) {
            int t=sta.top();
            sta.pop();
            vis[t]=1;
            color[t]=scnt;
            if (t==s)  break;
        }
    }
}
void solve() {
    while(scanf("%d%d", &n, &m)!=EOF) {
        for (int i=1; i<=n; i++) {
            scanf("%d", a+i);
        }
        init();
        for (int i=0; i<m; i++) {
            int a, b;  scanf("%d%d", &a, &b);
            add(a, b);
        }
        for (int i=1; i<=n; i++) {
            if (!dfn[i])  Tarjan(i);
        }
         for (int u=1; u<=n; u++) {
           for (int i=head[u]; ~i; i=e[i].next) {
                int v=e[i].v;
                if (color[u]!=color[v]) {
                    du[color[v]]++;
                }
            }
        }
        int ans=0, ansnum=0;
        for (int i=1; i<=scnt; i++) {
            if (!du[i]) {
                ans++;
                int num=INF;
                for (int j=1; j<=n; j++) {
                    if (color[j]==i) {
                        in[i]=min(a[j], in[i]);
                    }
                }
                ansnum+=in[i];
            }
        }
        printf("%d %d\n", ans, ansnum);
    }
}
int main() {
    int t = 1;
    //freopen("in.txt", "r", stdin);
    //scanf("%d", &t);
    while(t--)
        solve();
    return 0;
}
时间: 2024-10-26 17:12:04

强连通缩点— HDU1827的相关文章

Light OJ 1168 Wishing Snake 强连通缩点+哈密顿通路

题目来源:Light OJ 1168 Wishing Snake 题意:有点难看懂题意 看了一个小时再加别人的代码才懂意思 从0开始 输入的那些每一对u v 都要经过 就是从0到到达那些点 思路:首先缩点 每一个强连通分量里面的点都是可达的 缩点后的图是有向无环图 如果从0这个强连通分量可以出去到2个强连通分量 那么这两个强连通分量是不可能相互可达 所以可行的方案就是所有的强连通分量连成一线 一个一个串起来 除了第一个 出度是1入度是0和最后一个出度是0入度是1 其他都是入度等于出度是1 特判只

BZOJ 1051: [HAOI2006]受欢迎的牛 强连通缩点

题目链接: http://www.lydsy.com/JudgeOnline/problem.php?id=1051 题解: 强连通缩点得到DAG图,将图转置一下,对入度为零的点跑dfs看看能不能访问到所有的点. 代码: #include<iostream> #include<cstdio> #include<vector> #include<stack> #include<algorithm> #include<cstring> u

POJ3352Road Construction(边的双连通+强连通缩点)

Road Construction Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 8673   Accepted: 4330 Description It's almost summer time, and that means that it's almost summer construction time! This year, the good people who are in charge of the ro

hdu3861The King’s Problem (强连通 缩点+最小路径覆盖)

The King's Problem Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 1606 Accepted Submission(s): 584 Problem Description In the Kingdom of Silence, the king has a new problem. There are N cities in

UVA - 11324 The Largest Clique 强连通缩点+记忆化dp

题目要求一个最大的弱联通图. 首先对于原图进行强连通缩点,得到新图,这个新图呈链状,类似树结构. 对新图进行记忆化dp,求一条权值最长的链,每个点的权值就是当前强连通分量点的个数. /* Tarjan算法求有向图的强连通分量set记录了强连通分量 Col记录了强连通分量的个数. */ #include <iostream> #include<cstring> #include<cstdio> #include<string> #include<algo

HDU 4971 A simple brute force problem. 强连通缩点+最大权闭合图

题意: 给定n个项目,m个技术难题 下面一行n个数字表示每个项目的收益 下面一行m个数字表示攻克每个技术难题的花费 下面n行第i行表示 第一个数字u表示完成 i 项目需要解决几个技术难题,后面u个数字表示需要解决的问题标号. 下面m*m的矩阵 (i,j) = 1 表示要解决j问题必须先解决i问题. (若几个问题成环,则需要一起解决) 问:最大收益. 思路: 先给问题缩点一下,每个缩点后的点权就是这个点内所有点权和. 然后跑一个最大权闭合图. #include<stdio.h> #include

hdu 4635(强连通+缩点)

http://acm.hdu.edu.cn/showproblem.php?pid=4635 Strongly connected Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1381    Accepted Submission(s): 587 Problem Description Give a simple directed

poj2553 强连通缩点

The Bottom of a Graph Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 10114   Accepted: 4184 Description We will use the following (standard) definitions from graph theory. Let V be a nonempty and finite set, its elements being called ve

poj2186 强连通缩点

Popular Cows Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 29141   Accepted: 11779 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, you are given up to M (1 <= M &