题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=251
测模版:
#include <stdio.h> #include <iostream> #include <algorithm> #include <string.h> #include <queue> #include <vector> using namespace std; #define N 100005 #define M 200300 #define inf 10000000 struct Edge{ int from,to,next; bool cut; }edge[2*M]; int head[N],edgenum; int Low[N],DFN[N],Stack[N],Stack2[N];//Belong数组的值是1~block int Index,top,top2; int Belong[N],block;//新图的连通块标号(1~block) bool Instack[N], cut[N]; int bridge; //割桥数量 int add_block[N]; //add_block[i]表示删掉i点后增加的连通分量数 void addedge(int u,int v){ Edge E={u,v,head[u],0}; edge[edgenum]=E; head[u] = edgenum++; Edge E2={v,u,head[v],0};edge[edgenum]=E2;head[v] = edgenum++; } void Tarjan(int u,int pre){ int v, son = 0; Low[u] = DFN[u] = ++Index; Stack[top++] = u; Stack2[top2++] = u; Instack[u] = true; for(int i = head[u]; ~i ;i = edge[i].next){ v = edge[i].to; // 如果重边有效的话下面这句改成: if(v == pre && pre_num == 0){pre_num++;continue;} pre_num在for上面定义 int pre_num=0; if( v == pre )continue; if( !DFN[v] ) { son++; Tarjan(v,u); if(Low[u] > Low[v])Low[u] = Low[v]; if(Low[v] > Low[u]) { bridge++; edge[i].cut = edge[i^1].cut = true; } if(u != pre && Low[v] >= DFN[u])//不是树根 { cut[u] = true; add_block[u]++; } } else if(Low[u] > DFN[v])Low[u] = DFN[v]; } if(Low[u] == DFN[u]){ block++; do{ v = Stack[--top]; Instack[v] = false; Belong[v] = block; }while( v != u ); } if(u == pre && son > 1)cut[u] = true; if(u == pre)add_block[u] = son - 1; Instack[u] = false; top2--; } void work(int l, int r){ memset(DFN,0,sizeof(DFN)); memset(Instack,false,sizeof(Instack)); memset(cut, false, sizeof cut); Index = top = block = bridge = 0; top2 = 0; for(int i = l; i <= r; i++)if(!DFN[i])Tarjan(i,i); } vector<int>G[N];//点标从1-block void suodian(){ for(int i = 1; i <= block; i++)G[i].clear(); for(int i = 0; i < edgenum; i+=2){ int u = Belong[edge[i].from], v = Belong[edge[i].to]; if(u==v)continue; G[u].push_back(v), G[v].push_back(u); } } void init(){edgenum = 0; memset(head,-1,sizeof(head));} int g[110][110]; char buf[1010]; int main(){ int n; while(scanf("%d",&n),n){ gets(buf); memset(g,0,sizeof(g)); while(gets(buf)) { if(strcmp(buf,"0")==0)break; char *p = strtok(buf," "); int u; sscanf(p,"%d",&u); p = strtok(NULL," "); int v; while(p) { sscanf(p,"%d",&v); p = strtok(NULL," "); g[u][v]=g[v][u]=1; } } init(); for(int i = 1;i <= n;i++) for(int j = i+1;j <= n;j++) if(g[i][j]) { addedge(i,j); } work(1,n); int ans = 0; for(int i = 1; i <= n; i++)ans += cut[i]; printf("%d\n",ans); } return 0; }
UVA 315 求割点数,码迷,mamicode.com
时间: 2024-10-03 22:40:33