poj3694 Network

来源:互联网 发布:windows远程ubuntu 编辑:程序博客网 时间:2024/04/26 01:24

链接:http://poj.org/problem?id=3694

题意:有一个网络。问每添加一条边,整个新图中有多少条桥?

#include<cstdio>#include<cstring>#define MAXN 100005using namespace std;struct Edge{   int to;   int next;}edge[MAXN*4];int n,m;int ans,cnt,index;int head[MAXN],dfn[MAXN],low[MAXN],farther[MAXN],set[MAXN];//father[u]为当前u节点的父节点//set数组用于并查集中节点的划分void init(){index=ans=cnt=0;for(int i=1;i<=n;i++){set[i]=i;dfn[i]=0;head[i]=-1;farther[i]=0;}}void add(int u,int v){edge[cnt].to=v;    edge[cnt].next=head[u];    head[u]=cnt++;       edge[cnt].to=u;    edge[cnt].next=head[v];    head[v]=cnt++;}int find(int x){if(x!=set[x])set[x]=find(set[x]);return set[x];}int merge(int a,int b){int x=find(a);    int y=find(b);    if(x==y)return 0;else    set[y]=x;    return 1;}void tarjan(int u,int fa){   int i,v;   dfn[u]=low[u]=++index;   for(i=head[u];i!=-1;i=edge[i].next)   {        v=edge[i].to;    if(v==fa)continue;    if(!dfn[v])    {        tarjan(v,u);farther[v]=u;   //设置当前节点v的父节点为u    if(low[u]>low[v])    low[u]=low[v];    if(dfn[u]<low[v])   //edge(u,v)为割边,ans++    ans++;    elsemerge(u,v);//否则,属于一个连通分量,就合并,利用并查集缩点    }    else if(low[u]>dfn[v])    low[u]=dfn[v];   }}void lca(int u,int v){while(u!=v){        while(dfn[u]>=dfn[v]&&u!=v)//点u的深度大于点v的深度    {        if(merge(u,farther[u]))//如果u和father[u]不在同一个连通分量,则桥减一,因为势必形成环    ans--;    u=farther[u];  //点u向上爬    }    while(dfn[v]>=dfn[u]&&u!=v)    {        if(merge(v,farther[v]))    ans--;    v=farther[v];    }}}int main(){   int q,i,CASE=0;   int a,b;   while(scanf("%d%d",&n,&m)!=EOF)   {   if(!n&&!m)return 0;init();    for(i=0;i<m;i++)    {scanf("%d%d",&a,&b);        add(a,b);    }    scanf("%d",&q);tarjan(1,-1);printf("Case %d:\n",++CASE);    for(i=0;i<q;i++)    {scanf("%d%d",&a,&b);lca(a,b);    printf("%d\n",ans);    }   }}

再附上网上的另一种方法,应该说方法一样的,只是一个是直接通过标记桥来判断。

思路:求双连通分量,利用并查集缩点,形成一棵树,树边肯定都是桥,然后每对点x,y,找原图中x,y点对应的新图中的点,如果不是一个点,则向上找它们的LCA,因为它们之间连了一条边,所以这些点到它们的LCA之间的边都不是割边了,找LCA时,先将两点上升到同一层次,然后一起再向上找父亲节点,其间遇到桥就把桥的标记删除,并且答案减1。

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <vector>#include <queue>#define MAXN 100005#define MAXM 555555#define INF 1000000000using namespace std;struct Edge{    int v, next;}edge[MAXM];int low[MAXN], dfn[MAXN], index, vis[MAXN];int e, n, m, head[MAXN];int cnt, bridge[MAXN], father[MAXN];void init(){    e = 0, index = 0, cnt = 0;    memset(vis, 0, sizeof(vis));    memset(dfn, 0, sizeof(dfn));    memset(bridge, 0, sizeof(bridge));    memset(head, -1, sizeof(head));    for(int i = 1; i <= n; i++) father[i] = i;}void insert(int x, int y){    edge[e].v = y;    edge[e].next = head[x];    head[x] = e++;}void tarjan(int u){    vis[u] = 1;    dfn[u] = low[u] = ++index;    for(int i = head[u]; i != -1; i = edge[i].next)    {        int v = edge[i].v;        if(!vis[v])        {            father[v] = u;            tarjan(v);            low[u] = min(low[u], low[v]);            if(low[v] > dfn[u])            {                cnt++;                bridge[v] = 1;            }        }        else if(vis[v] == 1 && v != father[u]) low[u] = min(low[u], dfn[v]);    }    vis[u] = 2;}void LCA(int u, int v){    while(dfn[u] > dfn[v])      {        if(bridge[u])  cnt--, bridge[u] = 0;        u = father[u];    }    while(dfn[v] > dfn[u])    {        if(bridge[v]) cnt--, bridge[v] = 0;        v = father[v];    }    while(u != v)    {        if(bridge[u]) cnt--, bridge[u] = 0;        if(bridge[v]) cnt--, bridge[v] = 0;        u = father[u];        v = father[v];    }}void ask(){    int q, u, v;    scanf("%d", &q);    while(q--)    {        scanf("%d%d", &u, &v);        LCA(u, v);        printf("%d\n", cnt);    }    printf("\n");}int main(){    int cas = 0;    while(scanf("%d%d", &n, &m) != EOF)    {        if(n == 0 && m == 0) break;        printf("Case %d:\n", ++cas);        init();        int x, y;        while(m--)        {            scanf("%d%d", &x, &y);            insert(x, y);            insert(y, x);        }        tarjan(1);        ask();    }    return 0;}

转自:http://blog.csdn.net/sdj222555/article/details/7211644

http://blog.csdn.net/zhengnanlee/article/details/22646327

0 0
原创粉丝点击