【图论】【桥】【HDU4612】Warm up

原题链接:点击打开链接

题目大意为:

给你一个n (n<=200 000)点,m (m<=1000 000)条边的无向图(无向图含重边)。

询问在图中添加一条边后,能够使得新图中的桥最少。

在无向图中的任意一条路径上,如果路径中含有桥,我们只要连接路径的两个端点,就可以将路径中的桥取缔。

因此,题目变为在图中找一条含有桥的数量最多的路径。

算法设计:

利用塔尖算法标记出无向图中的所有桥。

把图中所有的桥设置权值为1,非桥的边权值为0。

此时,在途中给找出一条权值最大的路径。

看网上的题解,说可以建立一颗包涵所有桥的树,然后求树的直径。但我的方法并没有建立树,而是直接在原有的图像图中,利用Heap+Bfs(类似于Heap+Dijkstra)找出的最长链。

而在题目中,由于数据比较大,会发生栈溢出,因此要添加语句:

#pragma comment(linker,"/STACK:102400000,1024000")


代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<map>
#include<algorithm>
#include<map>
#include<stack>
#pragma comment(linker,"/STACK:102400000,1024000")
using namespace std;
const int inf=999999999;
const int maxn=200005;
struct Edge{
    int from, to;
    int dist;
    Edge (){};
    Edge (int a,int b):from(a),to(b),dist(0){}
};
vector<Edge>edges;
vector<int>G[maxn];
int cnt_bridge;

void add(int a,int b){
    Edge e(a,b);
    edges.push_back(e);
    e.from=b;e.to=a;
    edges.push_back(e);
    int mm=edges.size();
    G[a].push_back(mm-2);
    G[b].push_back(mm-1);
}
int pre[maxn];
bool iscut[maxn];
int dfs_clock;
int low[maxn];
class Cuts_Bridges{
    public:
    int n;
    void init(int n){
        this->n=n;
        for(int i=1;i<=n;i++)G[i].clear();
        edges.clear();
        memset(iscut,0,sizeof(iscut));
        memset(pre,0,sizeof(pre));
        dfs_clock=0;
        cnt_bridge=0;
    }
    int dfs(int u,int fa,int lastEdge){
        int lowu=pre[u]=++dfs_clock;
        int child=0;
        for(int i=0;i<G[u].size();i++){
            Edge &e=edges[G[u][i]];
            int v=e.to;
            if(!pre[v]){
                child++;
                int lowv=dfs(v,u,G[u][i]);
                lowu=min(lowv,lowu);
                if(lowv>=pre[u]){
                    iscut[u]=true;
                    if(lowv>pre[u]){
                        e.dist=edges[G[u][i]^1].dist=1;
                        cnt_bridge++;
                    }
                }
            }
            else if(pre[v]<pre[u]&&lastEdge!=(G[u][i]^1))
                lowu=min(lowu,pre[v]);
        }
        if(fa<0&&child==1)iscut[u]=0;
        low[u]=lowu;
        return lowu;
    }
}Do;
bool done[maxn];
int d[maxn];
struct HeapNode{
      int d,u;
      bool operator<(const HeapNode& rhs)const {
            return d<rhs.d;
      }
};
void Dijkstra(int s,int n){
      priority_queue<HeapNode>Q;
      for(int i=0;i<=n;i++)d[i]=-inf;
      d[s]=0;
      memset(done,0,sizeof(done));
      HeapNode inp;
      inp.d=0;
      inp.u=s;
      Q.push(inp);
      while(!Q.empty()){
            HeapNode x=Q.top();
            Q.pop();
            int u=x.u;
            if(done[u])continue;
            done[u]=true;
            for(int i=0;i<G[u].size();i++){
                  Edge &e=edges[G[u][i]];
                  if(done[e.to])continue;
                  if(d[e.to]<d[u]+e.dist){
                        d[e.to]=d[u]+e.dist;
                        inp.d=d[e.to];
                        inp.u=e.to;
                        Q.push(inp);
                  }
            }
      }
}

int solve(int n){
    Dijkstra(1,n);
    int max=-inf,p=1;
    for(int i=1;i<=n;i++){
        if(d[i]>max){
            max=d[i];p=i;
        }
    }
    Dijkstra(p,n);
    max=-inf,p=1;
    for(int i=1;i<=n;i++)if(d[i]>max){
        max=d[i];p=i;
    }
    return max;
}

int main(){
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF&&(n||m)){
        Do.init(n);
        int a,b;
        for(int i=1;i<=m;i++){
            scanf("%d%d",&a,&b);
            add(a,b);
        }
        Do.dfs(1,-1,-1);
        int tmp=solve(n);
        printf("%d\n",cnt_bridge-tmp);
    }
    return 0;
}

/**
8 10
1 2
1 3
2 3
3 4
5 8
4 5
4 6
4 3
5 6
6 7
ans:0


8 9
1 2
1 3
2 3
3 4
5 8
4 5
4 6
5 6
6 7
ans:1


4 4
1 2
1 3
1 4
2 3
ans:0

**/



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值