ac next to small spanning tree

road repair plan

Time Limit: 3000  ms | Memory Limit: 65535  KB
Difficulty: 5
describe

General Nan led many troops, and they were stationed in N different cities. These cities were numbered from 1 to N. Due to the inconvenience of transportation, General Nan planned to build roads.

It is now known which cities can build roads, and if so, how much it will cost.

Now, the strategist has found a way to build a road that can connect all the cities with the least cost.

However, General Nan said that the pattern formed by this road construction plan is very unlucky, and I want Xiaogong to calculate whether there is another scheme with the same cost as the previous one. Now you can help Xiaogong write a program to calculate it. .

enter
Input an integer T (1<T<20) in the first line, indicating the number of test data groups The first line of
each test data group is two integers V, E, (3<V<500,10<E<200000) respectively represent the number of cities and the number of roads between cities. The data ensures that all cities are connected by road.
Subsequent E lines, each line has three numbers ABL, indicating that the road construction cost between city A and city B is L.
output
Output Yes or No for each set of test data (if there are more than two minimum cost schemes, output Yes, if there is only one minimum cost scheme, output No)
sample input
2
3 3
1 2 1
2 3 2
3 1 3
4 4
1 2 2
2 3 2
3 4 2
4 1 2
Sample output
No

Yes


There are generally two ways to find the sub-minimum spanning tree for topic analysis:

a. Use Kruskal to generate a minimum spanning tree first and save the subscripts of the edges on each tree, then traverse the edges on these trees, and then delete the edges on each tree --> rebuild the tree- ->Update the minimum weight value-->Recovery process, every time you delete an edge of the tree, the original tree is destroyed, the rebuilt tree must not be the original tree, and the minimum weight of the rebuilt tree is the next smallest. , note that if the bridge is deleted every time the edge is deleted, which will lead to the disconnection of the graph, so in Kruskal, it is necessary to use and check the number of connected components in the statistical graph. If the entire graph is not connected, return to infinity , so that this update of the weights must fail.

Complexity O (n-1*complexity of Kruskal after optimization)


#include<iostream>//Import input and output stream header files
#include<algorithm>//Import header file
using namespace std;//Import standard namespace
typedef struct edge//The structure that defines the edge
{
    int v,w,d;//Define the two endpoints of a side and its side length
    bool is_delete;//Define whether to delete the flag
} Edge;
#define MAXN 200007//Define the maximum side length
#define MAXNUM 0x3f3f3f3f//Define infinite value
Edge bian[MAXN];//Create an array of edges
int pre[MAXN];//Define the array of parent nodes of the collection
int n,e;//Define the number of edges and the number of points
int MST_id[MAXN];//Define the subscript of the tree to save the array
int mid_i;//The subscript of the spanning tree array
int cnt;//Define the number of components in the graph
bool cmp(Edge a,Edge b)
{
    return a.d<b.d;
}
int Find(int x)//compression path
{
    int temp,p=x;
    while(x!=pre[x])
    x=pre[x];//First find the root node of the set to which x belongs
    while(p!=x)//Update all root nodes on the path compressed
    {
        temp=pre[p];//Path traversal from x to root node
        pre[p]=x;
        p=temp;
    }
    return x;//Return the root node of the set
}
int kruskal(int p)//Enter Kruskal algorithm
{
    int sum=0;//Define the minimum spanning tree weight and sum
    for(int i=0;i<e;i++)//traverse each edge
    {
        int p1=Find(bian[i].v);
        int p2=Find(bian[i].w);
        if(bian[i].is_delete==false&&p1!=p2)//If this edge is not marked for deletion, and the two point sets do not have a parent node
        {
            cnt--;//The number of sets minus one
            pre[p1]=pre[p2];//The parent node changes
            sum+=bian[i].d;//Weights and the weights of this edge
            if(p==1)//If it is the first generation
            {
                MST_id[mid_i++]=i;//Record the id of the edge of the minimum spanning tree
            }
            if(cnt==1)
                break;
        }
    }
    if(cnt==1)//If the last full graph is connected, return the weight and
    return sum;
    else//Otherwise return infinity
        return MAXN;
}
void init()//Initialize the parent node and the number of sets cnt
{
    for(int i=0;i<=n;i++)
        pre[i]=i;
        cnt=n;
}
intmain()
{
    ios::sync_with_stdio(false);//Optimize input and output
    int ncase;//Define the number of test groups
    cin>>ncase;
    while(ncase--)
    {
        cin>>n>>e;//Given the number of vertices and edges
       mid_i=0;
        init();//Initialization
        for(int i=0; i<e; i++)
        {
            int v,w,d;
            cin>>v>>w>>d;
            bian[i].d=d;
            bian[i].v=v;
            bian[i].w=w;//Build a map
            bian[i].is_delete=false;
        }
        sort(bian,bian+e,cmp);//sort
        int sum=kruskal(1);//Get the minimum weight and mark the edge of the minimum spanning tree
         int tsum = MAXNUM;
        for(int i=0;i<mid_i;i++)
        {
            //cout<<mid_i<<endl;
            init();//Each initialization
            bian[MST_id[i]].is_delete=true;//Delete an edge of the minimum spanning tree
            tsum=min(kruskal(0),tsum);//Update the minimum value
            bian[MST_id[i]].is_delete=false;//Restore this edge
        }
        if(tsum==sum)//If the number is greater than 0, it exists
        {
            cout<<"Yes"<<endl;
        }
        else
            cout<<"No"<<endl;
    }
}
 
  

The second is to use Puri to find the largest edge in the tree to see if there is an equivalent in the original image. If there is, it means that it is not unique.

O(n^2)

#include<iostream>//Import input and output stream functions
#include<string.h>//Use memset
using namespace std;//Import standard namespace
#define MAXN 505//Define the maximum number of fixed points
#define MAXNUM 0x3f3f3f3f//Define infinity
int vis[MAXN];//Access the tag array
int graph[MAXN][MAXN];//Matrix graph
int n,e;//Number of vertices, number of edges
int low[MAXN];//Save the vertex of the built tree to the minimum value of each point
int MST[MAXN][MAXN];//The minimum value on the path from i to j
int is_MST[MAXN][MAXN];//Whether it is in the tree
int pre[MAXN];//Another node on the edge of the determined point
int csum=MAXNUM;
int sum=0;
void init()
{
    memset(graph, 0x3f, sizeof(graph));//Initialize the graph
    for(int i=0;i<=n;i++)
        graph[i][i]=0;//Set yourself and yourself to 0
      memset(MST,0,sizeof(MST));//initialize to 0
    memset(is_MST,0,sizeof(is_MST));//initialize to 0
csum=MAXNUM;
 sum=0;
}
bool prim(int s)//prim algorithm
{


    for(int i=1;i<=n;i++)
    {
        low[i]=graph[s][i];//The distance from each point to s
        pre[i]=s;//The direct predecessor of each point is s
        vis[i]=0;//Initialize that each point has not been visited
    }
    vis[s]=1;//The s point has been set and visited
    for(int j=1;j<n;j++)//loop n-1 times
    {
        int tmin=MAXN;//
        int fa=0;//
        int ti = -1;
        for(int i=1;i<=n;i++)
        {
            if(vis[i]==0&&low[i]<tmin)
            {
                tmin=low[i];
                ti = i;
            }
        }//Find the smallest low and subscript
        sum+=tmin;
            vis[ti]=1;//Set as found
            fa=pre[ti];//Take out another point on the side where the point ti is located
            is_MST[ti][fa]=is_MST[fa][ti]=1;//Mark this edge as in the tree
            for(int i=1;i<=n;i++)
            {
                if(vis[i]==1&&i!=ti)
                {
                    MST[i][ti]=MST[ti][i]=max( MST[i][fa],low[ti]);//Update the largest point from other points in the tree to the point just found the largest edge on the path
                }
                if(!vis[i]&&low[i]>graph[ti][i])//If it has not been visited, s relax low
                {
                    low[i]=graph[ti][i];
                    for [i] = ti;
                }
            }
        }

        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<i;j++)
            {
                if(is_MST[i][j]==0&&MST[i][j]!=MAXNUM)//If there is an edge and it is not in the tree
                {
                     //res=min(res,mst-path[i][j]+g[i][j]); Find the specific csum
                     csum=min(csum,sum-MST[i][j]+graph[i][j]);//Find the next smallest spanning tree
                    if(graph[i][j]==MST[i][j])//If there is an equivalent maximum edge in the original graph, it must exist
                    {
                        //return true;
                    }
                }
            }
        }
        return false;
}
intmain()
{
    ios::sync_with_stdio(false);
    int ncase;
    cin>>ncase;
   // ios::sync_with_stdio(false);
    while(ncase--)
    {
        cin>>n>>e;
        init();
        for(int i=0;i<e;i++)
        {
            int v,w,d;
            cin>>v>>w>>d;
            graph[v][w]=d;
            graph[w][v]=d;
          //  cout<<i<<endl;
        }//Build a map
prim(1);
    if(sum==csum)//If the original is the same as the new one, then output yes
    {
        cout<<"Yes"<<endl;
    }
    else
    {
        cout<<"No"<<endl;
    }
    }
    return 0;
}
 
 

Or use that sentence sparingly.

Dot more with Kruskal





Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326398211&siteId=291194637