UVA - 11838 Come and Go && UVA - 11770 Lighting Away (强连通分量)

链接 :



http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=27318

链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=20874

11838 :求一张图可否任意两点可达 。直接判断整个图是否强连通。

#pragma comment(linker, "/STACK:10240000,10240000")
#include <algorithm>
#include <iostream>
#include <sstream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <set>
#include <map>
#define mod 4294967296
#define MAX 0x3f3f3f3f
#define lson o<<1, l, m
#define rson o<<1|1, m+1, r
#define SZ(x) ((int)ans.size())
#define MAKE make_pair
#define INFL 0x3f3f3f3f3f3f3f3fLL
#define mem(a) memset(a, 0, sizeof(a))
const double pi = acos(-1.0);
const double eps = 1e-9;
const int N = 2005;
const int M = 20005;
typedef long long ll;
using namespace std;

int n, m;
vector <int> G[N];
int pre[N], low[N], scc[N], dfs_clock, scc_cnt;
stack <int> S;
void dfs(int u) {
    pre[u] = low[u] = ++dfs_clock;
    S.push(u);
    for(int i = 0; i < G[u].size(); i++) {
        int v = G[u][i];
        if(pre[v] == 0) {
            dfs(v);
            low[u] = min(low[u], low[v]);
        } else if(scc[v] == 0) {
            low[u] = min(low[u], pre[v]);
        }
    }
    if(low[u] == pre[u]) {
        scc_cnt++;
        for(;;) {
            int x = S.top(); S.pop();
            scc[x] = scc_cnt;
            if(x == u) break;
        }
    }
}
void find_scc() {
    dfs_clock = scc_cnt = 0;
    mem(scc);
    mem(pre);
    for(int i = 0; i < n; i++) {
        if(pre[i] == 0) dfs(i);
    }
}
int vis[N];
int main()  {

    //freopen("in.txt","r",stdin);

    while(cin >> n >> m && n + m) {

        for(int i = 0; i < n; i++) G[i].clear();

        for(int i = 0; i < m; i++) {
            int x, y, w;
            scanf("%d%d%d", &x, &y, &w);
            x--, y--;
            G[x].push_back(y);
            if(w == 2) G[y].push_back(x);
        }

        find_scc();

        int ans = 1;
        if(scc_cnt == 1) {
            ans = 1;
        } else ans = 0;

        printf("%d\n", ans);
    }

    return 0;
}

11770 :与11504多米诺骨牌几乎为同一题。强连通缩点后找出所有入度为0的点。

#pragma comment(linker, "/STACK:10240000,10240000")
#include <algorithm>
#include <iostream>
#include <sstream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <set>
#include <map>
#define mod 4294967296
#define MAX 0x3f3f3f3f
#define lson o<<1, l, m
#define rson o<<1|1, m+1, r
#define SZ(x) ((int)ans.size())
#define MAKE make_pair
#define INFL 0x3f3f3f3f3f3f3f3fLL
#define mem(a) memset(a, 0, sizeof(a))
const double pi = acos(-1.0);
const double eps = 1e-9;
const int N = 10005;
const int M = 20005;
typedef long long ll;
using namespace std;

int n, m;
vector <int> G[N];
int pre[N], low[N], scc[N], dfs_clock, scc_cnt;
stack <int> S;
void dfs(int u) {
    pre[u] = low[u] = ++dfs_clock;
    S.push(u);
    for(int i = 0; i < G[u].size(); i++) {
        int v = G[u][i];
        if(pre[v] == 0) {
            dfs(v);
            low[u] = min(low[u], low[v]);
        } else if(scc[v] == 0) {
            low[u] = min(low[u], pre[v]);
        }
    }
    if(low[u] == pre[u]) {
        scc_cnt++;
        for(;;) {
            int x = S.top(); S.pop();
            scc[x] = scc_cnt;
            if(x == u) break;
        }
    }
}
void find_scc() {
    dfs_clock = scc_cnt = 0;
    mem(scc);
    mem(pre);
    for(int i = 0; i < n; i++) {
        if(pre[i] == 0) dfs(i);
    }
}
int vis[N];
int main()  {

    //freopen("in.txt","r",stdin);

    int T, ca = 1;
    cin >> T;
    while(T--) {

        for(int i = 0; i < n; i++) G[i].clear();
        cin >> n >> m;
        for(int i = 0; i < m; i++) {
            int x, y;
            scanf("%d%d", &x, &y);
            x--, y--;
            G[x].push_back(y);
        }

        find_scc();

        mem(vis);
        for(int u = 0; u < n; u++) {
            for(int i = 0; i < G[u].size(); i++) {
                int v = G[u][i];
                if(scc[u] != scc[v]) {
                    vis[ scc[v] ]++;
                }
            }
        }

        int cnt = 0;
        for(int i = 1; i <= scc_cnt; i++) {
            if(vis[i] == 0) cnt++;
        }

        printf("Case %d: %d\n", ca++, cnt);

    }

    return 0;
}
时间: 2025-01-04 17:38:05

UVA - 11838 Come and Go && UVA - 11770 Lighting Away (强连通分量)的相关文章

UVA 11770 Lighting Away

RunID User Problem Result Memory Time Language Length Submit Time 2482977 zhyfzy J Accepted 0 KB 138 ms C++ 4.8.2 2322 B 2014-07-24 15:18:54 [题目大意] 一个有向图,每对一个结点操作,就可以触发连锁反应,使得该结点及它直接或间接指向的点均获得标记,问至少需要操作多少个结点使得所有结点获得标记 [题解] 缩点+DFS 首先能想到入度为0的点一定需要操作,但是

UVA 11504 - Dominos(强连通分量)

UVA 11504 - Dominos 题目链接 题意:给定一个多米诺骨牌的有向图,为最多要推几个才能全倒 思路:强连通分量,缩点后找出度数为0的点就是答案 代码: #include <cstdio> #include <cstring> #include <vector> #include <stack> #include <algorithm> using namespace std; const int N = 100005; vector

UVA 12167 - Proving Equivalences(强连通分量+缩点)

UVA 12167 - Proving Equivalences 题目链接 题意:给定一些已经存在的等价性证明,要求全部等价,需要在多最少几次证明 思路:先求出强连通分量,然后进行缩点,在缩点后的图上统计入度和出度为0结点的最大值,就是需要加的边数,注意如果整个图已经是强连通,就直接是答案 代码: #include <cstdio> #include <cstring> #include <vector> #include <stack> #include

UVA 11324 The Largest Clique (强连通分量缩点,图DP)

题目: http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=25&page=show_problem&problem=2299 题意: 给你一个有向图,求一个点集合的最大大小,使得此点集合中对于任意点对(u,v),有从u到v或者从v到u的边 方法: 先找强连通分量缩点,每个强连通分量显然满足条件,然后在缩点后的图中找到一条权值最大的路径,权值为此路径的点权之和,点权为这个

uva 11324 The Largest Clique(强连通分量缩点+DAG动态规划)

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=25&page=show_problem&problem=2299 题意:输入n和m,有n个点和m条有向边,求出一个节点集合包括的节点个数最多,而且该节点内的不论什么两点a,b,要么a能到达b,要么b能到达a,要么a和b互相到达. 思路:强连通分量缩点形成有向无环图DAG,把缩点后的每一个点的权值置为该强连通分量的节点个

UVA 11324 - The Largest Clique(强连通分量+缩点)

UVA 11324 - The Largest Clique 题目链接 题意:给定一个有向图,要求找一个集合,使得集合内任意两点(u, v)要么u能到v,要么v能到u,问最大能选几个点 思路:强连通分量,构造出scc之后,缩点,每个点的权值是集合点个数,然后做一遍dag找出最大权值路径即可 代码: #include <cstdio> #include <cstring> #include <vector> #include <stack> #include

UVA - 315 Network 和 UVA - 10199 (求割顶)

链接 :  http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=20837 http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=21278 求割顶的裸题. UVA - 315 #include <algorithm> #include <iostream> #include <sstream> #include <cstrin

UVA 11636 Hello World,LA 3602 DNA Consensus String,UVA 10970 Big Chocolate,UVA 10340 All in All,UVA 11039 Building Designing

课程好紧啊,只能刷点水题了,几乎都是贪心. UVA 11636 Hello World 二的幂答案就是二进制长度减1,不是二的幂答案就是是二进制长度. #include<cstdio> int main() { int n,kas = 0; while(scanf("%d",&n),n>0){ int r = 0; for(n--;n;n>>=1) r++; printf("Case %d: %d\n",++kas,r); }

UVA - 11324 The Largest Clique (DAG + 强连通分量)

题目大意:给出一张有向图G,求一个结点数最大的结点集,使得该点集中任意两个结点u和v满足: 要么u可到达v,要么v可以到达u(u和v互相可达也可以) 解题思路:u和v相互可达的时候,就是两个结点在同一个强连通分量内的时候 首先要保证集合里面的点可达:强连通分量就满足集合内的点都相互可达.所以第一件事就是找出所有的强连通分量,并统计出每个强连通分量内的结点数 然后找出每个强连通分量之间的关系,也就是找出两个强连通分量之间的桥,连接可连接的强连通分量 最后将每个强连通分量收缩,得到SCC图.此时的S