首页 > 其他 > 详细

TLE君的强连通日记

时间:2014-03-18 21:32:39      阅读:535      评论:0      收藏:0      [点我收藏+]

如果您愿意转载,请注明出处不谢


TLE君的强连通日记


HDU1269 迷宫城堡

判断是不是强连通图。数据超级水,事实上随便写个dfs就能过了


HDU2767 Proving Equivalences

添加最少数量的有向边把原图变成强连通图

这道题靠dfs果然已经水不过去了,于是只好老老实实学了一下tarjan (其实tarjan的精髓就是如何用栈?)

先tarjan把强连通分量缩点,得到有向无环图,设有a个点没有出度(方便起见称为叶子),b个点没有入度(根)

则答案就是max(a,b)

假设a > b

首先呢,至少需要a条边,才有能让这a+b个点连通,

然后,从每个叶子引出一条边连向第一片叶子不能到达的叶子的根,最多用a-1条边,就可以让第一片叶子能够到达其他所有的叶子,

最后,把剩下的没有连出的叶子连向第一片叶子,就变成回路了

a < b的情况也类似

by the way,感觉强连通tarjan算法就是dfs树+栈,代码不长但是却处理了有向图的所有情况


HDU3836 Equivalent Sets

和上一题是一个东西,只是换了一个背景


HDU1827 Summer Holiday

点有权,选出最少的点及最小的点权和,使得所有的点都能够被被选点通过有向边遍历到

scc缩个点先,得到新的有向无环图,新图的每个点的点权为对应原强连通分量中的最小点权

然后,最少点数就是新图入度为0的点的数量,最小点权和就是新图入度为0的点的权和


HDU3072 Intelligence System

选择最小权边集,使得所有的点都能够被从0遍历(强连通分量费用为0)

显然先scc缩个点,新图的点权为原图连向该强连通分量的最小边权,0所在的强连通分量权值为0

答案就是新图的点权和


HDU3861 The King’s Problem

其实就是用最少的不相交有向路径覆盖强连通分量缩点后的所有的点

感觉tarjan在这里简直就是个模板,然后缩完点就没他什么事了= =

scc缩点,然后dfs遍历新图,当前节点与随便一个子节点共用一条路径,其他子节点则新开路径 (没什么最优性质,把父节点尽量往下连就好了。。)

然后输出答案


HDU3639 Hawk-and-Chicken

缩点,新图的点权为对应强连通分量内的点数量,

然后问题就变成怎么统计有向无环图的每个子树节点权和

这个。。暴力dfs就过去了= =

无可奈何时用暴力,大胆暴力出奇迹,暴力才是真爱啊。。


HDU3594 Cactus

判断原图是不是有向仙人掌

有向图仙人掌:

1:强连通

2:每条边属于且只属于一个环

我先睡了一觉,然后起来先用tarjan判完强连通,然后yy了一个看起来很对的dfs瞬间就过去了。。

然后AC代码被某巨巨的神数据叉出了翔,然后又各种打补丁,现在看起来大概是木有问题了- -b

真尼玛欢乐的题目啊

附代码,有兴趣的童鞋帮我再叉一叉,有神数据请留言谢谢。。

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>

using namespace std;

#define snuke(it,x) for (__typeof((x).begin()) it = (x).begin();                 it != (x).end(); it ++)

const int N = 22222;
int stack[N],instack[N],top,tot,tim,dfn[N],low[N],n,vis[N],dep[N];
vector<int> G[N];

bool dfs(int u,int deep) {
        vis[u] = 1;
        dep[u] = deep;
        snuke(it,G[u]) {
                if (!instack[u]) {
                        instack[u] = 1;
                        stack[top++] = u;
                }
                int v = *it;
                if (!vis[v]) {
                        if (!dfs(v,deep+1)) return false;
                } else if (instack[v]) {
                        int pre = dep[u];
                        while (true) {
                                int c = stack[--top];
                                if (dep[c]!=pre) return false;
                                pre --;
                                instack[c] = 0;
                                if (c==v) break;
                        }
                } else {
                        return false;
                }
        }
        return true;
}

void tarjan(int u) {
        dfn[u] = low[u] = ++tim;
        stack[top++] = u;
        instack[u] = 1;
        snuke(it,G[u]) {
                int v = *it;
                if (!dfn[v]) {
                        tarjan(v);
                        low[u] = min(low[u],low[v]);
                } else if (instack[v]) {
                        low[u] = min(low[u],low[v]);
                }
        }
        if (dfn[u]==low[u]) {
                while (true) {
                        int c = stack[--top];
                        instack[c] = 0;
                        if (c==u) break;
                }
                tot ++;
        }
}

void scc() {
        tot = top = tim = 0;
        memset(dfn,0,sizeof(dfn));
        memset(instack,0,sizeof(instack));
        for (int i = 0; i < n; i ++) if (!dfn[i]) tarjan(i);
}

int main() {
        int cas;
        scanf("%d",&cas);
        while (cas--) {
                scanf("%d",&n);
                for (int i = 0; i < n; i ++) {
                        G[i].clear();
                }
                int a,b;
                while (scanf("%d%d",&a,&b)==2 && (a||b)) {
                        G[a].push_back(b);
                }
                if (n==1) {
                        puts("YES");
                        continue;
                }

                scc();
                if (tot>1) {
                        puts("NO");
                        continue;
                }

                top = 0;
                memset(instack,0,sizeof(instack));
                memset(vis,0,sizeof(vis));
                bool ans = dfs(0,0);
                puts(ans ? "YES" : "NO");
        }
        return 0;
}


TLE君的强连通日记,布布扣,bubuko.com

TLE君的强连通日记

原文:http://blog.csdn.net/hei_nero/article/details/21477077

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!