Road Construction(poj 3352)

题意:求最少天几条边,使这个无向图变成双连通图。

/*
  tarjan缩点后,形成一棵树,求出叶子节点数tot,答案是(tot+1)/2
*/
#include<cstdio>
#include<cstring>
#include<iostream>
#define N 1010
using namespace std;
int num[N],low[N],instack[N],vis[N],s[N],in[N],belong[N],top,cnt,indexx;
int head[N],n,m;
struct node
{
    int v,pre;
};node e[N*2];
void add(int i,int x,int y)
{
    e[i].v=y;
    e[i].pre=head[x];
    head[x]=i;
}
void tarjan(int u,int fa)
{
    num[u]=low[u]=++indexx;
    vis[u]=instack[u]=1;
    s[++top]=u;
    for(int i=head[u];i!=-1;i=e[i].pre)
      if((fa^1)!=i)
      {
          int v=e[i].v;
          if(!vis[v])
          {
              tarjan(v,i);
              low[u]=min(low[v],num[u]);
          }
          else if(instack[v])
            low[u]=min(low[v],low[u]);
      }
    int x;
    if(num[u]==low[u])
    {
        ++cnt;
        do
        {
            x=s[top--];
            instack[x]=0;
            belong[x]=cnt;
        }while(u!=x);
    }
}
void work()
{
    for(int i=1;i<=m;i++)
    {
        int x,y;scanf("%d%d",&x,&y);
        add(i*2-2,x,y);add(i*2-1,y,x);
    }
    for(int i=1;i<=n;i++)
      if(!vis[i])tarjan(i,-1);
    for(int i=1;i<=n;i++)
      for(int j=head[i];j!=-1;j=e[j].pre)
        if(belong[i]!=belong[e[j].v])
          in[belong[e[j].v]]++;
    int tot=0;
    for(int i=1;i<=cnt;i++)
      if(in[i]==1)tot++;
    printf("%d\n",(tot+1)/2);
}
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        top=cnt=indexx=0;
        memset(num,0,sizeof(num));
        memset(low,0,sizeof(low));
        memset(instack,0,sizeof(instack));
        memset(vis,0,sizeof(vis));
        memset(s,0,sizeof(s));
        memset(head,-1,sizeof(head));
        memset(e,0,sizeof(e));
        memset(in,0,sizeof(in));
        memset(belong,0,sizeof(belong));
        work();
    }
    return 0;
}
时间: 2024-10-12 06:07:22

Road Construction(poj 3352)的相关文章

POJ 3352 Road Construction(图论-tarjan)

Road Construction Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 8647   Accepted: 4318 Description It's almost summer time, and that means that it's almost summer construction time! This year, the good people who are in charge of the ro

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 - 3352 Road Construction(边双连通分支)

1.给定一个连通的无向图G,至少要添加几条边,才能使其变为双连通图. 2.POJ - 3177 Redundant Paths(边双连通分支)(模板)  与这道题一模一样.代码就改了下范围,其他都没动... 3. //边双连通分支 /* 去掉桥,其余的连通分支就是边双连通分支了.一个有桥的连通图要变成边双连通图的话, 把双连通子图收缩为一个点,形成一颗树.需要加的边为(leaf+1)/2(leaf为叶子结点的个数) POJ 3177 给定一个连通的无向图G,至少要添加几条边,才能使其变为双连通图

POJ 题目 Road Construction(双连通)

Road Construction Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 9353   Accepted: 4648 Description It's almost summer time, and that means that it's almost summer construction time! This year, the good people who are in charge of the ro

POJ 3204 Ikki&#39;s Story I - Road Reconstruction(最大流)

POJ 3204 Ikki's Story I - Road Reconstruction 题目链接 题意:给定一个有向图,求出最大流后,问哪些边增加容量后,可以使最大流增加 思路:对于一个可以增加的,必然原来就是满流,并且从源点到汇点,的一条路径上,都是还有残留容量的,这样只要从源点和汇点分别出发dfs一遍,标记掉经过点,然后枚举满流边,如果两端都是标记过的点,这个边就是可以增加的 代码: #include <cstdio> #include <cstring> #include

HDU 5813 Elegant Construction(优雅建造)

HDU 5813 Elegant Construction(优雅建造) Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Description 题目描述 Being an ACMer requires knowledge in many fields, because problems in this contest may use physics, biology, and

hdu 4081 Qin Shi Huang&#39;s National Road System(最小生成树+dp)

同样是看别人题解才明白的 题目大意—— 话说秦始皇统一六国之后,打算修路.他要用n-1条路,将n个城市连接起来,并且使这n-1条路的距离之和最短.最小生成树是不是?不对,还有呢.接着,一个自称徐福的游方道士突然出现,他说他可以不消耗任何人力财力,使用法术凭空造一条路,路的长度无所谓,但是只能造一条.那么问题来了,徐福希望将两座人口数最多的城市连接起来,而秦始皇希望将最长的路修好.最后折中了一下, 将A/B最大的一条路用法术修出来.其中A是两座城市的人口和,B是除了用法术修的路以外,其它需要修建的

HDU 1325 Is It A Tree? (POJ 1308)

并查集问题... 这题以前做过-- 以前做过-- 做过-- 过-- 不过重做时候被吭得异常之爽-- 在判断 vis[i]的时候.我记得标准C++是非0 即为真. 而我用C++ 提交的时候 if(vis[i]) 去直接给我WA了. 用G++ 就AC了...然后改成if(vis[i]==1) 交C++ 就AC了. 特瞄的我每次初始化都把 vis[i] 都赋值为 0 了..都能出这种错? 求路过大神明示我的错误. 题意是判断是否是一棵树. 不能存在森林,用并查集合并,每个点的入度不能超过1. 比如 1

HDU4081Qin Shi Huang&#39;s National Road System(最小生成树+DFS)

Qin Shi Huang's National Road System Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4227    Accepted Submission(s): 1465 Problem Description During the Warring States Period of ancient China(4