• 【POJ 3177】Redundant Paths


    http://poj.org/problem?id=3177
    又写了一遍手动栈。。。
    把边双都缩点,缩成一棵树,答案就是树中度数为1的点的个数除2上取整。
    为什么呢?因为1个度数为1的点的树需要多连0条边,2个度数为1的点的树需要多连1条边,3个度数为1的点的树需要多连2条边。
    然后对于n(n>3)个度数为1的点的树,连一次边后再缩点能变成有n-2个度数为1的点的树。
    无向图边双跟有向图强连通分量的求法很像喔,重点在于特判后继节点是否是自己的father连过来的边。

    #include<cstdio>
    #include<bitset>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    
    const int N = 5003;
    const int M = 10003;
    
    bitset <N> inst;
    struct node {int nxt, to;} E[M << 1];
    int cnt = 1, tot = 0, bel[N], point[N], cur[N], st[N], sta[N], top, statop, fa[N], low[N], dfn[N], n, m, fae[N];
    
    void ins(int u, int v) {E[++cnt] = (node) {point[u], v}; point[u] = cnt;}
    
    void tarjan(int x) {
    	st[top = 1] = x;
    	while (top) {
    		int u = st[top];
    		if (!dfn[u]) {
    			inst[sta[++statop] = u] = 1;
    			dfn[u] = low[u] = ++cnt;
    		}
    		if (cur[u]) {
    			if (cur[u] == fae[u]) {cur[u] = E[cur[u]].nxt; continue;}
    			int v = E[cur[u]].to;
    			if (inst[v]) low[u] = min(low[u], dfn[v]);
    			else if (!dfn[v]) fa[st[++top] = v] = u, fae[v] = cur[u] ^ 1;
    			cur[u] = E[cur[u]].nxt;
    		} else {
    			low[fa[u]] = min(low[fa[u]], low[u]);
    			if (dfn[u] == low[u]) {
    				++tot;
    				while (sta[statop] != u) {
    					bel[sta[statop]] = tot;
    					inst[sta[statop]] = 0;
    					--statop;
    				}
    				bel[u] = tot;
    				inst[u] = 0;
    				--statop;
    			}
    			--top;
    		}
    	}
    }
    
    int du[N];
    
    int main() {
    	scanf("%d%d", &n, &m);
    	int u, v;
    	for (int i = 1; i <= m; ++i) {
    		scanf("%d%d", &u, &v);
    		ins(u, v); ins(v, u);
    	}
    	
    	for (int i = 1; i <= n; ++i) cur[i] = point[i];
    	cnt = 0;
    	for (int i = 1; i <= n; ++i)
    		if (!dfn[i])
    			tarjan(i);
    	
    	for (int i = 1; i <= n; ++i)
    		for (int j = point[i]; j; j = E[j].nxt)
    			if (bel[i] != bel[E[j].to] && E[j].to > i)
    				++du[bel[i]], ++du[bel[E[j].to]];
    	
    	int ret = 0;
    	for (int i = 1; i <= tot; ++i)
    		if (du[i] == 1) ++ret;
    	printf("%d
    ", (ret + 1) >> 1);
    	return 0;
    }
    
  • 相关阅读:
    vector常规用法(leedcode)
    creaor小游戏数据表配置引发的相关问题
    cocos2dx conversion to dalvik format failed
    Java中如何实现列表对象(List)的灵活查找?/java中Listgen根据某个元素获取对象
    MySql忘记root用户密码
    命令行模式下备份和恢复mysql数据库
    mysql开启日志
    Python操作Excel文件
    Python操作Json文件
    Python操作xml文件
  • 原文地址:https://www.cnblogs.com/abclzr/p/6640643.html
Copyright © 2020-2023  润新知