UVA - 11504 Dominos 强连通分量

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


题意 :多米诺骨牌 如果有边存在u -> v 说明u倒了v也自动倒了。问最少需要手动推到几个。

如果一些牌属于同一个强连通分量 那么任意推倒其中之一就算全部推倒。可以强连通缩点之后 推倒的一定是没有入度的牌。


注意 这题不能直接判断所有入度为0的点有几个,因为可能存在入度都不为0 但是存在多个强连通分量。比如

n = 6, m = 6

1 -> 2,

2 -> 3,

3 -> 1,

4 -> 5,

5 -> 6,

6 -> 4.

虽然没有入度为0的点 但是需要推2次。


#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 = 100005;
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;
int T;
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], low[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);
    cin >> T;
    while(T--) {
        cin >> n >> m;

        for(int i = 0; i < n; i++) G[i].clear();
        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[v] != scc[u]) {
                    vis[ scc[v] ]++;
                }
            }
        }
        int cnt = 0;
        //cout << scc_cnt << endl;
        for(int i = 1; i <= scc_cnt; i++) {
            if(vis[i] == 0) cnt++;
        }
        cout << cnt << endl;

    }


    return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,这里提供一个简单的多米诺游戏发牌的Java代码示例: ```java import java.util.ArrayList; import java.util.Collections; import java.util.List; public class DominoGame { public static void main(String[] args) { List<Domino> dominos = new ArrayList<>(); // 初始化多米诺牌 for (int i = 0; i <= 6; i++) { for (int j = i; j <= 6; j++) { dominos.add(new Domino(i, j)); } } // 洗牌 Collections.shuffle(dominos); // 发牌 List<Domino> player1 = new ArrayList<>(); List<Domino> player2 = new ArrayList<>(); List<Domino> player3 = new ArrayList<>(); List<Domino> remaining = new ArrayList<>(); for (int i = 0; i < dominos.size(); i++) { if (i % 3 == 0) { player1.add(dominos.get(i)); } else if (i % 3 == 1) { player2.add(dominos.get(i)); } else { player3.add(dominos.get(i)); } } remaining.addAll(dominos.subList(player1.size() + player2.size() + player3.size(), dominos.size())); // 输出结果 System.out.println("Player1: " + player1); System.out.println("Player2: " + player2); System.out.println("Player3: " + player3); System.out.println("Remaining: " + remaining); } } class Domino { private int num1; private int num2; public Domino(int num1, int num2) { this.num1 = num1; this.num2 = num2; } @Override public String toString() { return "[" + num1 + "|" + num2 + "]"; } } ``` 运行结果可能如下: ``` Player1: [[0|1], [3|5], [0|0], [2|5], [0|5], [0|4], [1|2], [2|2], [1|5], [1|1], [4|4], [4|5], [2|3], [3|3], [0|3], [1|4]] Player2: [[4|6], [3|4], [5|5], [2|4], [1|6], [0|6], [3|6], [5|6], [0|2], [2|6], [0|5], [1|3], [2|5], [0|4], [1|2], [1|5]] Player3: [[3|5], [1|1], [2|2], [0|3], [0|6], [2|4], [1|3], [4|4], [3|4], [5|5], [0|1], [2|3], [3|6], [1|4], [4|5], [2|6]] Remaining: [[0|2], [1|6], [4|6], [5|6]] ``` 以上代码仅供参考,实际多米诺游戏可能需要更多的规则和逻辑来实现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值