Test instructions: A number of people drive to the park party, but Park can stop the car is limited, for K. So these people have to drive to other families, stop and carpool to the party. In addition, the capacity of the car is unlimited, their home parking space is also unlimited.
To find the shortest total travel.
is to ask for a minimum spanning tree, but it cannot exceed K for one of these points.
Ideas:
1. take the park point out and find the rest of the points. The minimum spanning tree appears I unicom block
2. Select the smallest side adjacent to the park point in each block
The park point is already connected to the I side.
Park Point can be connected to K-point maximum
Get the sum value
3. The sum value of the i+1-->k bar shall be required
Add an edge to the tree each time to form a ring and then delete the Edge on a ring (maximum weight) take sum=min (sum,sum+ join Edge-delete edge) complexity O (n^2)
Third step due to the high complexity of the third step
Optimization: First record the weight of the VI->VP path and not directly connected to the VP max[i]
Add Edge time Fetch cost (VI,VP)-max [i] minimum join (VI,VP) edge
Then enumerate the edges that are not connected to the VP on the original path of VIVP, and find the edge of the most powerful value;
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <limits.h> #include < malloc.h> #include <ctype.h> #include <math.h> #include <string> #include <iostream># Include <algorithm> #include <vector> #include <string>using namespace Std;const int MAXN =111+5;const int maxe = 15000+5;const int INF = 460002326; #include <map>map<string,int>mp;map<string,int>:: Iterator It;int car,n,cost[maxn][maxn],sum,father[maxn];int best[maxn];bool vis[maxn];bool edge[maxn][maxn];bool use [Maxn];void dfs (int root)//marks each point in a connected block with its father{for (int i=1; i<n; i++) {if (Vis[i]&&edge[root][i]) {father[i]=root; Vis[i]=false; DFS (i); }}}void Prim (int s) {int MIN_I,MIN,DIS[MAXN],NUM[MAXN]; memset (vis,false,sizeof (VIS)); for (int i=0; i<n; i++) {dis[i]=cost[i][s]; num[i]=s;//the value of dis[i] at this point} dis[s]=0; vis[s]=use[S]=true; while (true) {min=inf,min_i=-1; for (int i=0; i<n; i++) {if (!use[i]&&!vis[i]&& (min_i==-1| | Min>dis[i]) {min_i=i; Min=dis[i]; }} if (Min==inf) break; Sum+=min; Vis[min_i]=true; use[min_i]=true;//the point edge[min_i][num[min_i]]=edge[num[min_i]][min_i]=true used to mark the connected block; for (int i=0; i<n; i++) {if (!use[i]&&!vis[i]&&dis[i]>cost[i][min_i]) { Num[i]=min_i; Dis[i]=cost[i][min_i]; }}} Min=inf; int root=-1; for (int i=0; i<n; i++)//Find the minimum distance of the connected block to the park point {if (vis[i]&&cost[0][i]<min&&i!=0)//In this tree {Min=cost[0][i]; root=i; }} Vis[root]=false; DFS (root);//root father[root]=0; Sum+=min;} int best (int j)//update the points at the top of the park path with the highest weighted value {if (father[j]==0)//Assuming Father is 0, recorded as-1 return best[j]=-1; if (best[j]!=-1) return best[j];//is assumed to already exist. Direct return int tmp=best (father[j]); if (tmp!=-1)//This indicates that its parent node is not connected to park {if (cost[tmp][father[tmp]]>cost[father[j]][j]) best[j]=tmp; else best[j]=j; } else best[j]=j;//its parent node is connected to the source to assign J to itself return Best[j];} void Solve () {int mst=0; memset (father,-1,sizeof (father)); memset (use,0,sizeof (use)); memset (Edge,false,sizeof (Edge)); Use[0]=true; for (int i=0; i<n; i++) {if (!use[i])//use used to mark {prim (i);//The smallest spanning tree mst++ except Park; }} for (int i=mst+1, i<n&&i<=car; i++) {memset (best)); for (int j=0; j<n; J + +) {if (j!=0&&best[j]==-1&&father[j]!=0) Best ( j); } int minadd=inf; int ax,bx,change; for (int j=0; j<n; J + +) {if (cost[0][j]!=inf&&father[j]!=0) {AX=BEST[J]; Bx=father[ax]; if (MINADD>COST[0][J]-COST[AX][BX])//cost[0][j] means the joined Edge COST[AX][BX] represents the broken edge { minadd=cost[0][j]-cost[ax][bx];//update the reduced value and the connected point change=j; }}} if (minadd>=0)//indicates that the sum value to be added has been given a minimum sum value of break; sum+=minadd;//update Ax=best[change]; Bx=father[ax]; Cost[ax][bx]=cost[bx][ax]=inf; father[change]=0; Cost[0][change]=cost[change][0]=inf; }}int Main () {int t; Freopen ("In.txt", "R", stdin); cin>>t; Mp.clear (); String s1,s2; int Val; for (int i=0, i<maxn; i++) for (int j=0; j<maxn; j + +) Cost[i][j]=inf; n=1,sum=0; mp["Park"]=0;//park is 0; for (int i=0; i<t; i++) {cin>>s1>>s2>>val; It=mp.find (s1);//map map Value if (It==mp.end ()) mp[s1]=n++; It=mp.find (S2); if (It==mp.end ()) mp[s2]=n++; if (cost[mp[s1]][mp[s2]]>val)//may have a heavy edge. Not really ....。 Cost[mp[s1]][mp[s2]]=cost[mp[s2]][mp[s1]]=val; } cin>>car; Solve (); cout<< "Total miles driven:" <<sum<<endl; return 0;}
poj1639 Picnic planning Minimum degree limit spanning tree