首页 > 代码库 > 无向图的联通分量
无向图的联通分量
无向图的联通分量环啊,桥啊,生成树的边啊,联通分量啊,就是一个东西
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 4161 7 6162 1 2163 1 3164 2 4165 3 4166 4 5167 5 6168 169 170 5 4171 1 2172 2 3173 2 4174 4 5175 176 177 4 4178 1 2179 2 3180 3 4181 4 1182 183 184 8 8185 1 2186 2 3187 2 4188 2 5189 3 4190 5 6191 6 7192 6 8193 194 195 Case #1: 1196 Case #2: 10197 Case #3: 0198 Case #4: 6199 200 */
无向图的联通分量
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。