• HDU 4612 Warm up(双连通分量缩点+求树的直径)


      思路:强连通分量缩点,建立一颗新的树,然后求树的最长直径,然后加上一条边能够去掉的桥数,就是直径的长度。

      树的直径长度的求法:两次bfs可以求,第一次随便找一个点u,然后进行bfs搜到的最后一个点v,一定是直径的一个端点(证明从略),第二次以点v为开头进行bfs,求出的最后一个点,就是直径的另一个端点,记录深度就是我们要求的长度。我这里是使用的bfs+dfs,是一样的,少开一个deep数组,节省一下空间吧……

      其实我一开始是不会求的,我以为随便一个叶子节点就可以做端点,交上去WA,当时还好奇感觉没错,结果随便一画,就错了……

      注意:这个题里面有重边,我们可以通过重边走回父亲节点,但不可以通过父亲边回到父亲节点,所以原先标记父亲的方式是不可以的,这里改成标记边,在Edge结构体中多加一个vis的变量,标记这个边是否被访问过,那这样重边就能正常访问了。

      这个题的数据量比较强,容易爆栈,STL的实用性就不强了,所以尽量使用数组模拟,数组能够开到更大的空间。

      感想:感觉这一块的题目真心很爱出错,这个题真是WA了好多次才过的,感觉oj不爱我了……

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    using namespace std;
    #define N 200020
    #define M 2000020
    struct Edge
    {
        int to,nxt,vis;
    } edge[M];
    int head[N],dfn[N],low[N],vis[N],sta[N],id[N];
    int tot,all,top,scc,bridge;
    void addedge(int a,int b,int flag)
    {
        edge[tot].to = b;
        edge[tot].nxt = head[a];
        edge[tot].vis = flag;
        head[a] = tot++;
    }
    void tarjan(int u)
    {
        vis[u] = 1;
        dfn[u] = low[u] = ++all;
        sta[top++] = u;
        for(int i = head[u]; i != -1; i = edge[i].nxt)
        {
            if(edge[i].vis) continue;
            int v = edge[i].to;
            edge[i].vis = edge[i^1].vis = 1;
            if(!dfn[v])
            {
                tarjan(v);
                low[u] = min(low[u],low[v]);
                if(low[v] > dfn[u]) bridge++;
            }
            else if(vis[v]) low[u] = min(low[u],dfn[v]);
        }
        if(low[u] == dfn[u])
        {
            scc++;
            int num;
            do
            {
                num = sta[--top];
                id[num] = scc;
                vis[num] = 0;
            }
            while(u != num);
        }
    }
    vector<int> tree[N];
    int treevis[N],maxdeep;
    void dfs(int u,int deep)
    {
        treevis[u] = 1;
        maxdeep = max(deep,maxdeep);
        int len = tree[u].size();
        for(int i = 0; i < len; i++)
        {
            int v = tree[u][i];
            if(!treevis[v])
            {
                dfs(v,deep+1);
            }
        }
    }
    void init()
    {
        memset(vis,0,sizeof(vis));
        memset(dfn,0,sizeof(vis));
        memset(id,0,sizeof(id));
        memset(low,0,sizeof(low));
        all = 0;
        top = 0;
        scc = 0;
        bridge = 0;
    }
    int que[N];
    int getstart()
    {
        int front,rear;
        front = rear = 0;
        que[rear++] = 1;
        treevis[1] = 1;
        while(front != rear)
        {
            int now = que[front++];
            int len = tree[now].size();
            for(int i = 0; i < len; i++)
            {
                int nxt = tree[now][i];
                if(treevis[nxt]) continue;
                treevis[nxt] = 1;
                que[rear++] = nxt;
            }
        }
        return que[--rear];
    }
    int main()
    {
        int n,m,a,b;
        while(~scanf("%d%d",&n,&m))
        {
            if(!n && !m) break;
            memset(head,-1,sizeof(head));
            tot = 0;
            for(int i = 0; i < m; i++)
            {
                scanf("%d%d",&a,&b);
                addedge(a,b,0);
                addedge(b,a,0);
            }
            init();
            tarjan(1);
            for(int i = 1; i <= scc; i++)
            {
                tree[i].clear();
            }
            for(int u = 1; u <= n; u++)
            {
                for(int i = head[u]; i != -1; i = edge[i].nxt)
                {
                    int v = edge[i].to;
                    if(id[u] != id[v])
                    {
                        int uu = id[u];
                        int vv = id[v];
                        tree[uu].push_back(vv);
                        tree[vv].push_back(uu);
                    }
                }
            }
            maxdeep = 0;
            memset(treevis,0,sizeof(treevis));
            int start = getstart();
            memset(treevis,0,sizeof(treevis));
            dfs(start,1);
            printf("%d
    ",scc-maxdeep);
        }
        return 0;
    }
  • 相关阅读:
    CSharpGL(26)在opengl中实现控件布局/渲染文字
    CSharpGL(25)一个用raycast实现体渲染VolumeRender的例子
    some OpenGL constants
    CSharpGL(24)用ComputeShader实现一个简单的图像边缘检测功能
    CSharpGL(23)用ComputeShader实现一个简单的ParticleSimulator
    CSharpGL(22)实现顺序无关的半透明渲染(Order-Independent-Transparency)
    CSharpGL(21)用鼠标拾取、拖拽VBO图元内的点、线或本身
    批量重命名文件
    [译]基于GPU的体渲染高级技术之raycasting算法
    CSharpGL(20)用unProject和Project实现鼠标拖拽图元
  • 原文地址:https://www.cnblogs.com/jifahu/p/5550615.html
Copyright © 2020-2023  润新知