题解 | #Puzzle: Wagiri#

Puzzle: Wagiri

https://ac.nowcoder.com/acm/contest/81601/D

输入时将qie存起来,将所有lun使用tarjan进行缩点,最后使用并查集, 将存起来的qie加上,看看是否能将所有点串起来

#include <bits/stdc++.h>

using namespace std;

const int N = 1e5 + 10, M = 1e6 + 10;

struct Edge{int u, v;};

int n, m;
int h[N], hs[N], e[M], ne[M], idx;
int dfn[N], low[N], timestamp;
int stk[N], top;
int id[N], dcc_cnt;
vector<int> dcc[N];

vector<Edge> qie;

bool in_ans[M];

int p[N];

vector<Edge> ans;

int find(int x) {
    if (p[x] != x) p[x] = find(p[x]);
    return p[x];
}

void merge(int x, int y) {
    int px = find(x), py = find(y);
    if (px == py) return;
    p[px] = py;
}

void add(int a, int b) {
    e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}

void tarjan(int u, int from) {
    dfn[u] = low[u] = ++ timestamp;
    stk[ ++ top] = u;
    
    for (int i = h[u]; i != -1; i = ne[i]) {
        int j = e[i];
        if (!dfn[j]) {
            tarjan(j, i);
            low[u] = min(low[u], low[j]);
        } else if (i != (from ^ 1)) {
            low[u] = min(low[u], dfn[j]);
        }
    }
    
    if (dfn[u] == low[u]) {
        dcc_cnt ++;
        int y;
        do {
            y = stk[top --];
            id[y] = dcc_cnt;
            dcc[dcc_cnt].push_back(y);
        } while (y != u);
    }
}

void solve() {
    cin >> n >> m;
    for (int i = 1; i <= n; i ++) h[i] = -1;
    
    for (int i = 1; i <= m; i ++) {
        int u, v; string w;
        cin >> u >> v >> w;
//         cout << u << " " << v << " " << w << endl;
        if (w == "Lun") {
            add(u, v); add(v, u);
        } else if (w == "Qie") { // 先把切边存起来
            qie.push_back((Edge){u, v});
        }
    }
    for (int i = 1; i <= n; i ++)
        if (!dfn[i])
            tarjan(i, -1);

    for (int i = 1; i <= n; i ++)
        if (!id[i]) {
            dcc_cnt ++;
            id[i] = dcc_cnt;
            dcc[dcc_cnt].push_back(i);
        }
    
    bool flag = true;
    
    for (int i = 1; i <= n; i ++) p[i] = i;
    
    for (int idx = 1; idx <= dcc_cnt; idx ++) {
        for (auto u : dcc[idx]) {
            for (int i = h[u]; i != -1; i = ne[i]) {
                int j = e[i];
                if (in_ans[i] || in_ans[i ^ 1] || id[j] != idx) continue;
                in_ans[i] = in_ans[i ^ 1] = true;
                ans.push_back((Edge) {u, j});
                merge(u, j);
            }
        }
    }
    
    for (auto e : qie) {
        if (find(e.u) == find(e.v)) continue;
        ans.push_back(e);
        merge(e.u, e.v);
    }
    
    for (int i = 1; i <= n; i ++)
        if (find(i) != find(1)) 
        {
            flag = false;
            break;
        }
    
    if (flag) {
        cout << "YES" << endl;
        cout << ans.size() << endl;
        for (auto a : ans) {
            cout << a.u << " " << a.v << endl;
        }
    } else {
        cout << "NO" << endl;
    }
//     for (int i = 1; i <= n; i ++) cout << dfn[i] << " " << low[i] << endl;
//     for (int i = 1; i <= n; i ++) {
//         for (int j = h[i]; j != -1; j = ne[j]) {
//             int k = e[j];
//             cout << k << " ";
//         }
//         cout << endl;
//     }
}

int main() {
    int t; t = 1;
    while (t --)
        solve();
}
全部评论

相关推荐

关于“实习生工资多少才算正常”,其实并没有一个放之四海而皆准的标准,但如果结合一线城市的生活成本、工作强度以及实习本身创造的价值来看,我个人认为6000&nbsp;元左右应当是一个基本及格线,也就是每天&nbsp;200&nbsp;多元。如果能达到&nbsp;300、400&nbsp;元一天,甚至更高,那无疑是更理想的状态。首先,从现实成本看,房租、通勤、餐饮几乎都是刚性支出。低于这个水平的实习,往往意味着实习生需要用家庭或存款“倒贴”工作,这在长期来看并不合理。实习本质上是学习,但并不等于“廉价劳动力”,更不应该是经济压力的来源。其次,愿意给实习生更高薪资的公司,通常不会是差公司。这至少说明两点:一是公司资金相对充足,不是靠压缩人力成本勉强维持;二是公司认可实习生的价值,希望你真正参与业务、创造产出,而不是只做边角料工作。很多高薪实习往往伴随着更规范的培养体系、更高的信息密度和更真实的项目经验。当然,高工资并不等于一切,但它往往是一个重要信号。能给到&nbsp;300、400&nbsp;元一天甚至更多的公司,往往对效率、能力和长期发展更有追求,也更可能处在一个有前景的赛道中。总结来说,实习工资不仅是钱的问题,更是公司态度、实力和发展前景的体现。在条件允许的情况下,争取一份“付得起你时间”的实习,本身就是一种理性选择。
北国牛马:你是不是忘了你一周只能上五天班,月薪6000那你日薪就得300了,日薪200一个月也就4000,也就刚好覆盖生活成本了
实习生工资多少才算正常?
点赞 评论 收藏
分享
2025-12-15 12:50
河北工程大学
sta666:我也是这个国际商业化的,三天,一天一面,就通过了,不过我是后端实习生,好好面感觉能过。
点赞 评论 收藏
分享
评论
3
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务