ZJU 2588 Burning Bridges - 无向图的桥

来源:互联网 发布:c语言ascii码对照表 编辑:程序博客网 时间:2024/06/05 08:55

题目大意

给出一个无向图,N个顶点M条边(N<10 000,M<100 000)。求出图中桥的个数及编号。注意,可能出现重边。

分析

题目就是要求无向图的桥。至于重边的处理,只要顶点ij之间有重边,那么这些重边任何一条都不可能是桥

由于数据量大,需要用邻接表来存无向图。

PE了无数次>_<,输出时每两个桥的编号之间有一个空格,行尾无空格;没两组测试数据之间有空行,末尾无空行;如果该组测试数据没有桥,第二行的空行不要输出。

 

  1. /*
  2. ZJU2588 Burning Bridges
  3. */
  4. #include <stdio.h>
  5. #include <memory.h>
  6. #define clr(a) memset(a,0,sizeof(a))
  7. #define N 10005
  8. #define M 100005
  9. #define MIN(a,b) ((a)>(b)?(b):(a))
  10. /*******************************************/
  11. typedef struct NodeStr{
  12.     int j,tag,id; struct NodeStr *next;
  13. }Node;
  14. Node mem[M*2];
  15. int memp,nid;
  16. int bridge[M]; //i->j,is bridge
  17. int nbridge;
  18. int addEdge(Node *e[],int i,int j){
  19.     Node* p;
  20.     for(p=e[i];p!=NULL;p=p->next) if(p->j==j) break;
  21.     if(p!=NULL){ p->tag++; return 0; }
  22.     p=&mem[memp++];
  23.     p->j=j; p->next=e[i]; e[i]=p; p->id=nid; p->tag=0;
  24.     return 1;
  25. }
  26. int anc[N],mark[N],deep[N]; //i可达祖先的最小编号;0,1,2访问标记;DFS深度
  27. int DFS(Node *e[],int i,int father,int dth,int cut[]){
  28.     int j,k,sons=0,count=0; Node *p,*q;
  29.     mark[i]=1; deep[i]=anc[i]=dth;
  30.     for(p=e[i];p!=NULL;p=p->next){
  31.         j=p->j;
  32.         if(j!=father && mark[j]==1) anc[i]=MIN(anc[i],deep[j]);
  33.         if(mark[j]==0){
  34.             count+=DFS(e,j,i,dth+1,cut);
  35.             sons++;
  36.             anc[i]=MIN(anc[i],anc[j]);
  37.             if((father==-1&&sons>1)||(father!=-1&&anc[j]>=deep[i])) cut[i]=1;
  38.             //if(anc[j]>deep[i]) brige[i][j]=1; //边(i,j)是桥
  39.             if(anc[j]>deep[i] && !p->tag) bridge[p->id]=++nbridge;
  40.         }
  41.     }
  42.     mark[i]=2;
  43.     return count+cut[i];
  44. }
  45. int Cutpoints_Link(Node *e[],int n,int cut[]){
  46.     int i,j,count=0;
  47.     for(i=0;i<n;i++) cut[i]=0;
  48.     memset(mark,0,sizeof(mark));
  49.     for(i=0;i<n;i++)if(mark[i]==0) count+=DFS(e,0,-1,0,cut);
  50.     return count;
  51. }
  52. /***************************************/
  53. int n,m;
  54. Node *e[N];
  55. int cut[N];
  56. int main()
  57. {
  58.     int i,j,k,n,m,T;
  59.     
  60.     scanf("%d",&T);
  61.     while(T--){
  62.         //init
  63.         memp=0; nid=0; clr(e);
  64.         //input
  65.         scanf("%d%d",&n,&m);
  66.         for(k=0;k<m;k++,nid++){
  67.             scanf("%d%d",&i,&j);
  68.             addEdge(e,i-1,j-1); addEdge(e,j-1,i-1);
  69.             bridge[nid]=0;
  70.         }
  71.         //bridge
  72.         nbridge=0; clr(bridge);
  73.         Cutpoints_Link(e,n,cut);
  74.         //output
  75.         printf("%d/n",nbridge);
  76.         for(i=0,k=nbridge;i<m;i++){
  77.             if(bridge[i]){
  78.                 printf("%d",i+1);
  79.                 if(--k) printf(" ");
  80.             }
  81.         }
  82.         if(nbridge )puts("");
  83.         if(T) puts("");
  84.     }
  85.     
  86.     return 0;
  87. }