zoukankan      html  css  js  c++  java
  • P3225 [HNOI2012]矿场搭建 题解

    这道题挺难的,可以加深对割点的理解,还有,排列组合好重要了,分连通块,然后乘法原理(加法原理计数什么的)

    传送门   https://www.luogu.org/problem/P3225

    省选oi题好难啊QAQ

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<vector>
    #define maxn 10000
    using namespace std;
    vector<int>G[maxn];
    void insert(int be, int en) {
    	G[be].push_back(en);
    }
    int low[maxn], dfn[maxn], vis[maxn], df;
    int cnt[maxn];
    void tarjan(int root ,int x) {
    	low[x] = dfn[x] = ++df;
    	int chal = 0;
    	for (int i = 0; i < G[x].size(); i++) {
    		int p = G[x][i];
    		if (!dfn[p]) {
    			tarjan(root, p);
    			chal++;
    			low[x] = min(low[x], low[p]);
    			if (root != x) {
    				if (low[p] >= dfn[x]) {
    					cnt[x] = 1;
    				}
    			}
    			else {
    				if (chal >= 2) {
    					cnt[root] = 1;
    				}
    			}
    		}
    		else {
    			low[x] = min(low[x], dfn[p]);
    		}
    	}
    }
    int num, cn;
    int gp;
    void dfs(int x) {
    	if (cnt[x]) return;
    	if (vis[x]) return;
    	num++;
    	vis[x] = gp;
    	for (int i = 0; i < G[x].size(); i++) {
    		int p = G[x][i];
    		if (cnt[p] && vis[p] != gp) {
    			cn++;
    			vis[p] = gp;
    		}
    		dfs(p);
    	}
    }
    int main() {
    	int m;
    	int ccc = 0;
    	while (~scanf("%d", &m) && m) {
    		int n = -1;
    		int be, en;
    		ccc++;
    		memset(dfn, 0, sizeof(dfn));
    		memset(vis, 0, sizeof(vis));
    		memset(cnt, 0, sizeof(cnt));
    		for (int i = 0; i < m; i++) {
    			scanf("%d %d", &be, &en);
    			insert(be, en);
    			insert(en, be);
    			n = max(be, n);
    			n = max(en, n);
    		}
    		for (int i = 1; i <= n; i++) {
    			if (!dfn[i]) tarjan(i, i);
    		}
    		long long ans1 = 0, ans2 = 1;
    		for (int i = 1; i <= n; i++) {
    
    			if (!vis[i] && !cnt[i]) {
    				cn = num = 0;
    				gp++;
    				dfs(i);
    
    				if (cn == 0) {
    					ans1 += 2;
    					ans2 *= num * (num - 1) / 2;
    				}
    				if (cn == 1) {
    					ans1 += 1;
    					ans2 *= num;
    				}
    			}
    		}
    		printf("Case %d: %lld %lld
    ",ccc, ans1, ans2);
    		for (int i = 0; i <= n; i++) G[i].clear();
    	}
    	return 0;
    }
    

      

    寻找真正的热爱
  • 相关阅读:
    LeetCode 21. 合并两个有序链表
    LeetCode 20. 有效的括号
    LeetCode 19. 删除链表的倒数第N个节点
    AI
    http
    IP地址
    wiodows /linux CMD
    git
    AI
    JS常用的获取值和设值的方法
  • 原文地址:https://www.cnblogs.com/lesning/p/11621628.html
Copyright © 2011-2022 走看看