您的位置:首页 > 其它

Critical Set(删除无向图的一个节点或者两个节点或者三个节点之后有几个连通分量?)

2014-09-16 17:18 537 查看


这是棒子的一家公司的一道编程题,写的累死了。
上题目吧,有一个无向图,任意两个定点,都能访问对方,如果我删除一个节点,如果任意两个节点不能访问了,那叫这个点是critical point;如果说删除一个不行,那么删除两个或者三个才行,那么叫critical set,最多删除三个。

题目

输入是一个文件,文件的格式如下

4

9 10

1 2 1 7 1 3 3 5 2 3 2 4 6 8 6 9 9 8 5 8 

9 12

1 2 1 5 2 5 2 3 5 6 3 6 3 4 6 7 7 8 4 8 8 9 4 9

5 7

1 2 1 3 1 5 2 5 4 5 2 4 3 4

6 11

1 2 1 6 2 6 1 3 2 3 3 4 4 5 5 6 2 4 3 6 2 5

说明一下,第一行是有多少case,没两行是一个case。一个case里,第一行是 顶点数与边数,第二行是每两个数为一单元,两个数表示两个顶点,这两个顶点之间有边。

输出是:

case #1 1 1 

case #2 2 2 5 

case #3 2 1 4 

case #4 3 2 3 5 

每行写一个case,最前面写case #几,之后第一个数表示有几个critical point,1表示一个,2表示两个,3表示3个,-1表示不存在critical set。

思路

先删除一个点,只要把与它相关的边删除即可,然后开始查找图有几个连通分量,如果连通分量超过2个,那么就是存在critical point;如果删除一个点不行,那么删除两个点,再检测联通分量,如果联通分量大于3,那么存在critical point;如果还不行,删除三个点,依然是检测连通分量,思路与上面是一样的。
怎么检测联通分量呢?
假如说刚开始每个点都是一个独自集合,如果两个点之间有条边,那么这两个集合并成一个集合。
下面看代码吧

#include<iostream>
#include<fstream>

using namespace std;
struct critiSec{
int pointNum;
int *pointData;
critiSec(int n):pointNum(n),pointData(NULL){}
};
class Union
{
private:
int* id;     // id[i] = parent of i
int* rank;  // rank[i] = rank of subtree rooted at i (cannot be more than 31)
int count;    // number of components
public:
Union(int N)
{
count = N;
id = new int
;
rank = new int
;
for (int i = 0; i < N; i++) {
id[i] = i;
rank[i] = 0;
}
}
~Union()
{
delete [] id;
delete [] rank;
}
int find(int p) {
while (p != id[p]) {
id[p] = id[id[p]];    // path compression by halving
p = id[p];
}
return p;
}
int getCount() {
return count;
}
bool connected(int p, int q) {
return find(p) == find(q);
}
void connect(int p, int q) {
int i = find(p);
int j = find(q);
if (i == j) return;
if (rank[i] < rank[j]) id[i] = j;
else if (rank[i] > rank[j]) id[j] = i;
else {
id[j] = i;
rank[i]++;
}
count--;
}
};

class Graph{
private:
int Vertexs;
int **Edges;
int **backEdges;
public:
Graph(int V,int **E):Vertexs(V){
Edges=new int*[Vertexs];
for(int i=0;i<Vertexs;i++){
Edges[i]=new int[Vertexs];
}
backEdges=new int*[Vertexs];
for(int i=0;i<Vertexs;i++){
backEdges[i]=new int[Vertexs];
}
for(int i=0;i<Vertexs;i++)
for(int j=0;j<Vertexs;j++){
Edges[i][j]=E[i][j];
backEdges[i][j]=E[i][j];
}
}
void deletePoint(int i){
for(int j=0;j<Vertexs;j++){
Edges[i][j]=0;
Edges[j][i]=0;
}
}

~Graph(){
for(int i=0;i<Vertexs;i++){
if(Edges[i])
delete []Edges[i];
}
if(Edges)
delete []Edges;
}
critiSec* CriticalSet();
int isConnect();
void deleteEdge(int i,int j){
Edges[i][j]=0;
Edges[j][i]=0;
}
void restoreEdge(int i){
for(int k=0;k<Vertexs;k++){
Edges[k][i]=backEdges[k][i];
Edges[i][k]=backEdges[i][k];
}
}

};

critiSec* Graph::CriticalSet(){
bool flag=false;
critiSec *cr=NULL;

for(int i=0;i<Vertexs;i++){
deletePoint(i);
if(3==isConnect()){
flag=true;
cr=new critiSec(1);
cr->pointData=new int(i);
cr->pointData[0]=i;
restoreEdge(i);
break;
}
restoreEdge(i);
}

if(!flag){
for(int i=0;i<Vertexs-1;i++){
deletePoint(i);
if(flag)
break;
for(int j=i+1;j<Vertexs;j++){
deletePoint(j);

if(4==isConnect()){
flag=true;
cr=new critiSec(2);
cr->pointData=new int[2];
cr->pointData[0]=i;
cr->pointData[1]=j;
break;
}
restoreEdge(j);
deleteEdge(i,j);
}
restoreEdge(i);
}
}
if(!flag){
for(int i=0;i<Vertexs-2;i++){
if(flag)
break;
deletePoint(i);
for(int j=i+1;j<Vertexs-1;j++){
if(flag)
break;
deletePoint(j);
for(int k=j+1;k<Vertexs;k++){
deletePoint(k);
if(5==isConnect()){
flag=true;
cr=new critiSec(3);
cr->pointData=new int[3];
cr->pointData[0]=i;
cr->pointData[1]=j;
cr->pointData[2]=k;
break;
}
restoreEdge(k);
deleteEdge(j,k);
deleteEdge(i,k);

}
restoreEdge(j);
deleteEdge(j,i);
}
restoreEdge(i);
}
}

if(!flag)
cr=new critiSec(-1);
return cr;
}

int Graph::isConnect(){
Union uniCon(Vertexs);
for(int i=0;i<Vertexs;i++){
for(int j=i+1;j<Vertexs;j++){
if(Edges[i][j])
uniCon.connect(i,j);
}
}

return uniCon.getCount();
}

int main(){
ifstream file;
ofstream out;
out.open("out.txt",ios::out);
file.open("graph.txt",ios::in);
if(file.fail()){
cout<<"open files fails"<<endl;
return 0;
}
int caseNum;
file>>caseNum;
for(int i=0;i<caseNum;i++){
int edgeNum,v;
file>>v>>edgeNum;
int **e=new int*[v];
for(int i=0;i<v;i++){
e[i]=new int[v];
memset(e[i],0,sizeof(int)*v);
}
int v1,v2;
for(int i=0;i<edgeNum;i++){
file>>v1>>v2;
e[v1-1][v2-1]=1;
e[v2-1][v1-1]=1;
}

Graph g(v,e);
critiSec *cr=g.CriticalSet();
switch(cr->pointNum){
case -1:
out<<"case #"<<i+1<<" "<<-1<<endl;
break;
default:
out<<"case #"<<i+1<<" "<<cr->pointNum<<" ";
for(int k=0;k<cr->pointNum;k++)
out<<cr->pointData[k]+1<<" ";
out<<endl;
}
delete []cr->pointData;
delete cr;
for(int i=0;i<v;i++)
delete []e[i];
delete []e;
}
out.close();
file.close();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐