hdu 4612 强连通

题意:有一些联通的地方,如果2点间只有一条路径,这样的边叫做桥,现在让你添加一个桥,使最后的桥最少,问最少的桥使多少?

  先求一次强连通分量,然后图就分成了几个块,将这几个块看做点,求出总共有多少条重建图中的边,然后再求出最长的边,这样答案就是总共

边数 - 最长的边的长度。原来的标记手法过了几题,但是做这题有点问题,用了另一个手法。

#pragma comment(linker, "/STACK:102400000,102400000")
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define INF 1000000001
#define ll __int64
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
const int MAXN = 200010;
struct node
{
    int to;
    int next;
    int vis;
}edge[1000010 * 2],a[1000010 * 2];
struct fnode
{
    int x;
    int val;
};
int n,m,ind,pre[MAXN],ins[MAXN],low[MAXN],dfn[MAXN],vis[MAXN],num[MAXN],fpre[MAXN];
int fp,len,p;
stack<int>s;
void Init()
{
    fp = 1;
    ind = 0;
    while(!s.empty())s.pop();
    memset(num,0,sizeof(num));
    memset(ins,0,sizeof(ins));
    memset(pre,-1,sizeof(pre));
    memset(vis,0,sizeof(vis));
    memset(dfn,0,sizeof(dfn));
    memset(low,0,sizeof(low));
}
void add(int x,int y)
{
    edge[ind].to = y;
    edge[ind].vis = 0;
    edge[ind].next = pre[x];
    pre[x] = ind ++;
}
void dfs(int rt,int k,int fa)
{
    s.push(rt);
    vis[rt] = ins[rt] = 1;
    low[rt] = dfn[rt] = k;
    for(int i = pre[rt]; i != -1; i = edge[i].next){
        int t = edge[i].to;
        if(edge[i].vis)continue;
        edge[i].vis = edge[i^1].vis = 1;
        //原来判断 fa != t 但是有重边的情况这种标记不行。
        if(!dfn[t]){
            dfs(t,k+1,rt);
            low[rt] = min(low[rt],low[t]);
        }
        else{
            low[rt] = min(dfn[t],low[rt]);
        }
    }
    if(low[rt] == dfn[rt]){
        while(!s.empty()){
            int temp = s.top();
            s.pop();
            num[temp] = fp;
            if(temp == rt)break;
        }
        fp ++;
    }
}
void add_b(int x,int y)
{
    a[ind].to = y;
    a[ind].next = fpre[x];
    fpre[x] = ind ++;
}
void build(int rt)
{
    vis[rt] = 1;
    for(int i = pre[rt]; i != -1; i=edge[i].next){
        int t = edge[i].to;
        if(!vis[t]){
            if(num[t] != num[rt]){
                add_b(num[t],num[rt]);
                add_b(num[rt],num[t]);
            }
            build(t);
        }
    }
}
void bfs(int rt)
{
    queue<fnode>q;
    fnode temp;
    temp.val = 0;
    temp.x = rt;
    vis[rt] = 1;
    q.push(temp);
    while(!q.empty()){
        temp = q.front();
        q.pop();
        for(int i = fpre[temp.x]; i != -1; i = a[i].next){
            int t = a[i].to;
            if(!vis[t]){
                fnode ft;
                ft.val = temp.val + 1;
                ft.x = t;
                vis[t] = 1;
                q.push(ft);
                if(ft.val > len){
                    len = ft.val;
                    p = ft.x;
                }
            }
        }
    }
}
int main()
{
    while(~scanf("%d%d",&n,&m)){
        if(!n && !m)break;
        Init();
        for(int i = 1; i <= m; i++){
            int x,y;
            scanf("%d%d",&x,&y);
            add(x,y);
            add(y,x);
        }
        for(int i = 1; i <= n; i++){
            if(!dfn[i]){
                dfs(i,1,-1);
            }
        }
        memset(vis,0,sizeof(vis));
        ind = 1;
        memset(fpre,-1,sizeof(fpre));
        for(int i = 1; i <= n; i++){
            if(!vis[i]){
                build(i);
            }
        }
        len = 0;
        p = 1;
        memset(vis,0,sizeof(vis));
        bfs(1);
        len = 0;
        memset(vis,0,sizeof(vis));
        bfs(p);
        fp -= 1;
        int ans = fp - 1 - len;
        //cout<<"fp = "<<fp<<" len = "<<len<<endl;
        cout<<(ans > 0 ? ans : 0)<<endl;
    }
    return 0;
}

 

posted @ 2016-04-03 20:02  sweat123  阅读(213)  评论(0编辑  收藏  举报