[雙連通分量] POJ 3694 Network

來源:互聯網
上載者:User

標籤:最佳化   any   lis   cpp   single   namespace   cal   memory   標記   

Network
Time Limit: 5000MS   Memory Limit: 65536K
Total Submissions: 9434   Accepted: 3511

Description

A network administrator manages a large network. The network consists of N computers and M links between pairs of computers. Any pair of computers are connected directly or indirectly by successive links, so data can be transformed between any two computers. The administrator finds that some links are vital to the network, because failure of any one of them can cause that data can‘t be transformed between some computers. He call such a link a bridge. He is planning to add some new links one by one to eliminate all bridges.

You are to help the administrator by reporting the number of bridges in the network after each new link is added.

Input

The input consists of multiple test cases. Each test case starts with a line containing two integers N(1 ≤ N ≤ 100,000) and M(N - 1 ≤ M ≤ 200,000).
Each of the following M lines contains two integers A and B ( 1≤ A ≠ B ≤ N), which indicates a link between computer A and B. Computers are numbered from 1 to N. It is guaranteed that any two computers are connected in the initial network.
The next line contains a single integer Q ( 1 ≤ Q ≤ 1,000), which is the number of new links the administrator plans to add to the network one by one.
The i-th line of the following Q lines contains two integer A and B (1 ≤ A ≠ B ≤ N), which is the i-th added new link connecting computer A and B.

The last test case is followed by a line containing two zeros.

Output

For each test case, print a line containing the test case number( beginning with 1) and Q lines, the i-th of which contains a integer indicating the number of bridges in the network after the first i new links are added. Print a blank line after the output for each test case.

Sample Input

3 21 22 321 21 34 41 22 12 31 421 23 40 0

Sample Output

Case 1:10Case 2:20

Source

2008 Asia Hefei Regional Contest Online by USTC、原題大意:輸入焦點的個數N和邊的個數M,接下來輸入整數Q代表詢問的次數,之後Q行有兩個整數A,B,表示將A與B相連。問每次詢問後割邊(橋)的數量。解題思路1:用tarjian找割邊並標記,之後用lca遍曆A與B到最近公用祖先的路徑,這段路上是割邊的處理掉,總數-1就可以了。                表示用鏈表寫的,各種慢,但是POJ資料太弱了,怎麼寫都能過。
#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;struct list  {   int v;   list *next;  };list *head[110010],*rear[110010];int father[110010],times,dfn[110010],low[110010],bridge[110010],bridgenum,n;int dep[110010];void init()  {    int i;    memset(head,0,sizeof(head));    memset(dep,0,sizeof(dep));    memset(rear,0,sizeof(rear));    for(i=1;i<=n;++i) father[i]=i;    memset(dfn,0,sizeof(dfn));    memset(low,0,sizeof(low));    memset(bridge,0,sizeof(bridge));    times=bridgenum=0;  }void insert(int a,int b)  {    if(rear[a]!=NULL)      {         rear[a]->next=new list;         rear[a]=rear[a]->next;} else head[a]=rear[a]=new list;rear[a]->v=b;rear[a]->next=NULL;return;  }void tarjian(int v)  {   bool flag=true;   dfn[v]=low[v]=++times;   dep[v]=dep[father[v]]+1;   for(list *p=head[v];p!=NULL;p=p->next)     {       if(p->v==father[v]&&flag)         {            flag=false;            continue;}  if(!dfn[p->v])    {       father[p->v]=v;       tarjian(p->v);       low[v]=min(low[v],low[p->v]);       if(low[p->v]>dfn[v])         {            ++bridgenum;            bridge[p->v]=1; }}else  low[v]=min(low[v],dfn[p->v]);   }  }void lca(int a,int b)  {   if(dep[a]<dep[b]) swap(a,b);   while(dep[a]!=dep[b])     {    if(bridge[a])       {      bridge[a]=0;      --bridgenum;  }a=father[a];  } while(a!=b)  {  if(bridge[a])    {    bridge[a]=0;    --bridgenum;  }if(bridge[b])    {    bridge[b]=0;    --bridgenum;  }a=father[a];b=father[b];  }   return;  }int main()  {   int m,i,a,b,q,ccase=0;   while(~scanf("%d%d",&n,&m),n&&m)     {       init();       for(i=0;i<m;++i)         {           scanf("%d%d",&a,&b);           insert(a,b);insert(b,a);}  tarjian(1);  scanf("%d",&q);  printf("Case %d:\n",++ccase);  for(i=1;i<=q;++i)    {       scanf("%d%d",&a,&b);       lca(a,b);       printf("%d\n",bridgenum);}   }   return 0;  }

解題思路2:在原來的基礎上用並查集最佳化,這種做法是看了大神們的解題思路寫出的。

                將雙連通的兩個點弄成一個集合,這樣在LCA時只要判斷是否是一個集合,將橋的數量減去即可。

#include<stdio.h>#include<string.h>struct list   {   int v;   list *next;  };list *head[111010],*rear[111010];int n,m,father[111010],dep[110010],low[110010],fath[110010],bridgenum;void init()  {   int i;   memset(head,0,sizeof(head));   memset(rear,0,sizeof(rear));   memset(dep,0,sizeof(dep));   memset(low,0,sizeof(low));   memset(fath,0,sizeof(fath));   for(i=1;i<=n;++i) father[i]=i;   bridgenum=0;  }void insert(int a,int b)  {   if(rear[a]!=NULL)     {       rear[a]->next=new list;       rear[a]=rear[a]->next;   } else head[a]=rear[a]=new list; rear[a]->v=b; rear[a]->next=NULL;  }int find(int x)  {   return father[x]==x?x:father[x]=find(father[x]);  }void merge(int x,int y)  {   int fx=find(x);   int fy=find(y);   if(fx!=fy) father[fx]=fy;  }void tarjian(int v,int deps)  {   bool flag=true;   dep[v]=low[v]=deps;   for(list *p=head[v];p!=NULL;p=p->next)     {       if(p->v==fath[v]&&flag)          {            flag=false;            continue;}       if(!dep[p->v])         {           fath[p->v]=v;           tarjian(p->v,deps+1);           if(low[v]>low[p->v]) low[v]=low[p->v];           if(low[p->v]<=dep[v]) merge(p->v,v);           else bridgenum++;}  else if(low[v]>dep[p->v]) low[v]=dep[p->v];   }  }void judge(int v)  {   int x=find(v);   int y=find(fath[v]);   if(x!=y)     {       --bridgenum;       father[x]=y;   }  }void lca(int u,int v)  {   while(dep[u]>dep[v])      {         judge(u);         u=fath[u];}  while(dep[u]<dep[v])    {       judge(v);       v=fath[v];}  while(u!=v)    {     judge(u);judge(v);     u=fath[u];v=fath[v];}  }int main()  {   int a,b,q,num=0;   while(~scanf("%d%d",&n,&m))     {       if(n==0&&m==0) break;       init();       while(m--)         {           scanf("%d%d",&a,&b);           insert(a,b);insert(b,a);}  printf("Case %d:\n",++num);  tarjian(1,1);  scanf("%d",&q);  while(q--)    {       scanf("%d%d",&a,&b);       if(find(a)!=find(b)) lca(a,b);       printf("%d\n",bridgenum);}  printf("\n");   }   return 0;  }

  

[雙連通分量] POJ 3694 Network

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.