上题目吧,有一个无向图,任意两个定点,都能访问对方,如果我删除一个节点,如果任意两个节点不能访问了,那叫这个点是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。
思路
#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[N];
rank = new int[N];
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;
}