无向图的联通分量

无向图的联通分量环啊,桥啊,生成树的边啊,联通分量啊,就是一个东西

 

Unique Path https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4055

这个题是把环去掉,其他的树上有n个点,就有n*(n-1)/2 对。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #include<vector>
  5 #include<queue>
  6 #include<stack>
  7 #define mt(a,b) memset(a,b,sizeof(a))
  8 using namespace std;
  9 typedef long long LL;
 10 class Tarjan_U { ///无向图连通分量缩点o(MV+ME)
 11     typedef int typec;///边权的类型
 12     static const int ME=200010;///边的个数
 13     static const int MV=10010;///点的个数
 14     struct Q{
 15         int u,v;
 16         typec w;
 17     }now;
 18     vector<Q> qiao;
 19     int Bcnt,Index,num[MV],dfn[MV],low[MV],belong[MV];
 20     stack<int> s;
 21     void addqiao(int u,int v,typec w){
 22         now.u=u;
 23         now.v=v;
 24         now.w=w;
 25         qiao.push_back(now);
 26     }
 27     void tarjan(int u) {
 28         s.push(u);
 29         dfn[u]=low[u]=++Index;
 30         int v;
 31         for (int i=g.head[u]; ~i; i=g.e[i].next) {
 32             if(g.e[i].vis)continue;
 33             g.e[i].vis=g.e[i^1].vis=true;
 34             v=g.e[i].v;
 35             if (!dfn[v]) {
 36                 tarjan(v);
 37                 low[u]=min(low[u],low[v]);
 38                 if(dfn[u]<low[v])
 39                     addqiao(u,v,g.e[i].w);
 40             } else low[u]=min(low[u],dfn[v]);
 41         }
 42         if(dfn[u]==low[u]) {
 43             Bcnt++;
 44             do {
 45                 v=s.top();
 46                 s.pop();
 47                 belong[v]=Bcnt;
 48                 num[Bcnt]++;
 49             } while(v!=u);
 50         }
 51     }
 52 public:
 53     struct G {
 54         struct E {
 55             int v,next;
 56             bool vis;
 57             typec w;
 58         } e[ME];
 59         int le,head[MV];
 60         void init() {
 61             le=0;
 62             mt(head,-1);
 63         }
 64         void add(int u,int v,typec w) {
 65             e[le].vis=false;
 66             e[le].v=v;
 67             e[le].w=w;
 68             e[le].next=head[u];
 69             head[u]=le++;
 70         }
 71     } g;
 72     void init() {
 73         g.init();
 74         Index=Bcnt=0;
 75         mt(num,0);
 76         mt(dfn,0);
 77         mt(low,0);
 78         qiao.clear();
 79         while(!s.empty()) s.pop();
 80     }
 81     void add(int u,int v,typec w) {///双向边
 82         g.add(u,v,w);
 83         g.add(v,u,w);
 84     }
 85     void solve(int n) {///传入点数,点下标1开始
 86         for(int i=1; i<=n; i++) {
 87             if(!dfn[i]) {
 88                 tarjan(i);
 89             }
 90         }
 91     }
 92     int getbcnt() {///强连通分量的个数
 93         return Bcnt;
 94     }
 95     int getbelong(int id) {///属于哪个分量,分量下标1开始
 96         return belong[id];
 97     }
 98     int getnum(int id) {///某个分量的点的个数
 99         return num[id];
100     }
101 } T;
102 const int M=1e5+10;
103 bool vis[M],need[M];
104 queue<int> q;
105 int bfs(int s) {
106     vis[s]=true;
107     while(!q.empty()) q.pop();
108     q.push(s);
109     int res=0;
110     while(!q.empty()) {
111         int u=q.front();
112         q.pop();
113         res++;
114         for(int i=T.g.head[u]; ~i; i=T.g.e[i].next) {
115             int v=T.g.e[i].v;
116             if(!vis[v]) {
117                 vis[v]=true;
118                 q.push(v);
119             }
120         }
121     }
122     return res;
123 }
124 int main() {
125     int t,n,m;
126     while(~scanf("%d",&t)) {
127         int cas=1;
128         while(t--) {
129             scanf("%d%d",&n,&m);
130             T.init();
131             while(m--) {
132                 int u,v;
133                 scanf("%d%d",&u,&v);
134                 T.add(u,v,1);
135             }
136             T.solve(n);
137             mt(need,0);
138             for(int i=1; i<=T.getbcnt(); i++) {
139                 if(T.getnum(i)>1) need[i]=true;
140             }
141             mt(vis,0);
142             for(int i=1; i<=n; i++) {
143                 if(need[T.getbelong(i)]) {
144                     vis[i]=true;
145                 }
146             }
147             LL ans=0;
148             for(int i=1; i<=n; i++) {
149                 if(!vis[i]) {
150                     LL dian=bfs(i);
151                     ans+=dian*(dian-1)/2;
152                 }
153             }
154             printf("Case #%d: %lld\n",cas++,ans);
155         }
156     }
157     return 0;
158 }
159 /**
160 4
161 7 6
162 1 2
163 1 3
164 2 4
165 3 4
166 4 5
167 5 6
168 
169 
170 5 4
171 1 2
172 2 3
173 2 4
174 4 5
175 
176 
177 4 4
178 1 2
179 2 3
180 3 4
181 4 1
182 
183 
184 8 8
185 1 2
186 2 3
187 2 4
188 2 5
189 3 4
190 5 6
191 6 7
192 6 8
193 
194 
195 Case #1: 1
196 Case #2: 10
197 Case #3: 0
198 Case #4: 6
199 
200 */
View Code

 

posted on 2014-11-10 22:04  gaolzzxin  阅读(300)  评论(0编辑  收藏  举报