70.最小生成树

删边问题(edges.pas

题目描述:连通图是指任意两个顶点都有路径可互相到达的图。

读入一个无向的连通图,输出最多能删掉多少条边,使这个图仍然连通。

输入格式:

第一行为图的顶点数N1<=N<=100)和边数M,它们之间用一个空格隔开,图中的顶点用1N的整数标号。接下来的M行,每行用两个数v1v2表示一条边。v1v2用一个空格隔开,表示这条边所连接的顶点的标号(v1<>v2),同一条边不会重复出现。

输出格式:

输出最多能删掉的边数。

输入输出样例:

 

输入edges.in

输出 edges.out

4 6

1 2

1 3

1 4

2 3

2 4

3 4

3

 

思路:寻找最小生成树,用总边数目减去最小生成树中的边的数目,直接用

      总边数-n+1就行了

代码:

#include

#include

using namespace std;

#include

struct Edge{

       int u,v,w,next;

};

Edge edge[1001];

int head[1001]={0},father[1001];

int visit[1001]={0},n,m,sum=0;//

int cmp(const Edge &a,const Edge &b)

{

       return a.w

}

void input()

{

       scanf("%d%d",&n,&m);

       for(int i=1;i<=m;++i)

       {

              scanf("%d%d",&edge[i].u,&edge[i].v);

              edge[i].w=i;

              edge[i].next=head[edge[i].u];

              head[edge[i].u]=i;

             

       }

}

int find(int x)

{

       if(father[x]!=x) father[x]=find(father[x]);

       return father[x];

}

int k;

void unionn(int a,int b)

{

       father[b]=a;

}

void kruskal()

{

       k=0;

       sort(edge+1,edge+m+1,cmp);

       for(int i=1;i<=n;++i)

       father[i]=i;

       for(int i=1;i<=m;++i)

       {

              int r1=find(edge[i].u);

              int r2=find(edge[i].v);

              if(r1!=r2)

              {

                     k++;

                     unionn(r1,r2);

                     sum++;

                     if(k==n-1) break;

              }

             

       }

}

      

int main()

{

       input();

       kruskal();

       if(k==n-1)//表示图能连通 ,一定是n-1条边

       cout<<m-sum<<endl;

       else cout<<"no way!"<<endl;//

       return 0;

}

原文地址:https://www.cnblogs.com/csgc0131123/p/5290322.html