E - Redundant Paths - poj 3177(缩点求叶子节点)

题意:给一个图,想让每两条路都有两条边相,不过特殊的是相同的边多次相连也被认为是一条边,现在求最少还需要添加几条边才能做到

分析:手欠没看清楚是相同的边不能相连,需要去重边,缩点后求出来叶子节点的数目即可。

***********************************************************************

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;

const int MAXN = 1e5+5;

struct Edge{int v, next;}e[MAXN];
int Head[MAXN], cnt;
void AddEdge(int u, int v)
{
    e[cnt].v = v;
    e[cnt].next = Head[u];
    Head[u] = cnt++;
}

int low[MAXN], dfn[MAXN], Index;
int Stack[MAXN], top;
int belong[MAXN], bnt;
int ru[MAXN];
bool use[5005][5005];

void InIt(int N)
{
    cnt = Index = top = bnt = 0;
    memset(use, 0, sizeof(use));
    for(int i=1; i<=N; i++)
    {
        Head[i] = -1;
        dfn[i] = 0;
        ru[i] = 0;
    }
}
void Tarjan(int u, int father)
{
    int v;

low[u] = dfn[u] = ++Index;
    Stack[++top] = u;

for(int j=Head[u]; j != -1; j=e[j].next)
    {
        v = e[j].v;
        if( !dfn[v] )
        {
            Tarjan(v, u);
            low[u] = min(low[u], low[v]);
        }
        else if(v != father)
            low[u] = min(low[u], dfn[v]);
    }

if(low[u] == dfn[u])
    {
        ++bnt;
        do
        {
            v = Stack[top--];
            belong[v] = bnt;
        }
        while( u != v );
    }
}

int main()
{
    int N, M;

while(scanf("%d%d", &N, &M) != EOF)
    {
        int i, j, u, v;

InIt(N);

while(M--)
        {
            scanf("%d%d", &u, &v);

if(use[u][v] == false)
            {
                AddEdge(u, v);
                AddEdge(v, u);
                use[u][v] = use[v][u] = true;
            }
        }

Tarjan(1, 1);

for(i=1; i<=N; i++)
        for(j=Head[i]; j!=-1; j=e[j].next)
        {
            if(belong[i] != belong[e[j].v])
            {
                ru[ belong[i] ]++;
            }
        }

int ans = 0;

for(i=1; i<=bnt; i++)
        {
            if(ru[i] == 1)
                ans++;
        }

printf("%d\n", (ans+1)>>1);
    }

return 0;

}

时间: 2024-08-26 20:04:59

E - Redundant Paths - poj 3177(缩点求叶子节点)的相关文章

Redundant Paths POJ - 3177(边双连通)

Redundant Paths POJ - 3177 题意:一个无向图(有重边!!),问至少还要加多少边使得去掉任意一条边后任意两点仍可互达. 和上题poj3352基本相同,不过dfs的时候,不能用v!=f来判断是否能走,而要用当前走的边和上一条边是不是反向边 1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 using namesp

Redundant Paths POJ - 3177(边—双连通分量)

题意: 在图中加边 看最少能通过加多少条边把 图变成边-双连通分量 解析: 先做一次dfs,不同的连通分量的low是不同的  注意重边 缩点 统计度为1的点  那么需要加的边为(ret+1)/2 #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <vector> #include

Redundant Paths POJ - 3177

无向图概念:(这里的x->y表示x和y之间有一条无向边)1.桥:对于一个无向图,如果删除某条边后,该图的连通分量增加,则称这条边为桥 比如1->2->3->4这样一个简单得图一共有3个桥,分别是1->2,2->3,3->4 1->2->3->4->1 这样就没有桥,因为删除任意一个边,任意两点还可以互相往来(因为是双向边嘛) 2.割点/割项:对于一个无向图,如果删除某个节点u后,该图的连通分量增加,则节点u为割项或关节点 1->2-&

POJ 3177 Redundant Paths POJ 3352 Road Construction(双连通)

POJ 3177 Redundant Paths POJ 3352 Road Construction 题目链接 题意:两题一样的,一份代码能交,给定一个连通无向图,问加几条边能使得图变成一个双连通图 思路:先求双连通,缩点后,计算入度为1的个数,然后(个数 + 1) / 2 就是答案(这题由于是只有一个连通块所以可以这么搞,如果有多个,就不能这样搞了) 代码: #include <cstdio> #include <cstring> #include <algorithm&

POJ 3177 Redundant Paths(无向图缩点)

Description: In order to get from one of the F (1 <= F <= 5,000) grazing fields (which are numbered 1..F) to another field, Bessie and the rest of the herd are forced to cross near the Tree of Rotten Apples. The cows are now tired of often being for

POJ3177 Redundant Paths (双联通缩点)

求对于给定一个连通图,加多少条边可以变成边双连通图. 一个有桥的连通图要变成边双连通图的话,把双连通子图收缩为一个点,形成一颗树.需要加的边为(leaf+1)/2 (leaf为叶子结点个数). 对于此题,有重边但重边不加入计算. 重边的话,要么在开始去掉,要么用桥来计算入度. 因为桥不属于任何一个边双连通分支,其余的边和每个顶点都属于且只属于一个边双连通分支.对于重边而言,只有一对边被标记为桥,而对于所有重边来言,belong[u]和belong[v]都是不一样的,那么如果用belong[u]!

[USACO06JAN]冗余路径Redundant Paths 无向图tarjan缩点

如题,缩完点后数一下有几个入度为1的scc,+1再/2即可. 教训:加一个cntf处理重边!否则重边会被认为是同一条. 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<vector> 6 using namespace std; 7 8 struct stack{ 9 vector<int> v;

创建二叉树求叶子节点个数

求二叉树叶子结点的个数,注意创建方法! //求二叉树中叶子结点的个数 #include<iostream> #define N 63 using namespace std; char str[] = "ab#d##c#e##"; //先建立根节点,然后再左右结点建立 int i = -1; typedef struct node { struct node *leftChild; struct node *rightChild; char data; }BiTreeNod

poj 3177 Redundant Paths (双联通)

/******************************************************* 题目:Redundant Paths (poj 2177) 链接:http://poj.org/problem?id=3177 算法:双联通+缩点 思路:先找出所有双联通分量,把这些分量缩成一个点 再找出所有度为一的点,用这些点数加一除2就可以了 ********************************************************/ #include<cs