版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_41661919/article/details/84883583
#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include<algorithm>
#include <set>
#include <queue>
#include <stack>
#include<vector>
#include<map>
#include<ctime>
#define ll long long
using namespace std;
const int N=36;
int v[N];//联通块标号
int ver[N];//邻接表边N的终点
int edge[N*N+100];//邻接表边N的权值
int head[N];//邻接表点N的最后一条边
int next[N];//邻接表边N的下一条边
int tot;//邻接表 中边数
int cnt;//联通块的数目
int ff1[N];
int ff2[N];
int ff3[N];
void add(int x,int y,int z)//邻接表加边
{
ver[++tot]=y;
edge[tot]=z;
next[tot]=head[x];
head[x]=tot;
}
void dfs(int x)//得到x所在的联通块
{
v[x]=cnt;
for(int i=head[x];i;i=next[i])
{
int y=ver[i];
if(v[y])continue;
dfs(y);
}
}
int dis[N][N];
map<string,int>mm;
int num;
int d[N];//prime中以点N为终点的那条边;
bool flag[N];
int prime(int index,int pos,int nn)//联通块标号、起点
{
for(int i=0;i<=32;++i)d[i]=999999999;
memset(flag,0,sizeof(flag));
d[pos]=0;
for(int i=1;i<nn;++i)
{
int x=0;
for(int j=1;j<=num;++j)
if(!flag[j]&&((x==0)||d[j]<d[x])&&v[j]==index)x=j;
flag[x]=1;
for(int j=head[x];j;j=next[j])
{
int y=ver[j];
if(!flag[y]&&v[y]==index)
{
if(edge[j]<d[y])
{
d[y]=edge[j];
ff2[y]=x;
}
d[y]=min(d[y],edge[j]);
}
}
}
int ans=0;
for(int i=1;i<=num;++i)
{
if(v[i]==index)ans+=d[i];
}
return ans;
}
int dfs2(int xx)//找1->xx的最长边
{
int ans=0;
for(int i=xx;i!=ff1[v[xx]];i=ff2[i])
{
ans=max(ans,dis[i][ff2[i]]);
}
return ans;
}
int main()
{
int n;
while(cin>>n)
{
memset(dis,0,sizeof(dis));
tot=cnt=0;
mm.clear();
memset(v,0,sizeof(v));
memset(ver,0,sizeof(ver));
memset(head,0,sizeof(head));
memset(next,0,sizeof(next));
memset(edge,0,sizeof(edge));
string str,t;
int x;
mm.insert(make_pair("Park",1 ));
num++;
for(int i=1;i<=n;++i)
{
cin>>str>>t>>x;
int d1,d2;
if(mm.find(str)==mm.end())
{
num++;
mm.insert(make_pair(str,num));
d1=num;
}
else
{
d1=mm.find(str)->second;
}
if(mm.find(t)==mm.end())
{
num++;
mm.insert(make_pair(t,num));
d2=num;
}
else
{
d2=mm.find(t)->second;
}
dis[d1][d2]=dis[d2][d1]=x;
add(d1,d2,x);
add(d2,d1,x);
}
int s;
cin>>s;
for(int i=2;i<=num;++i)
{
if(v[i])continue;
cnt++;
dfs(i);
}
//cout<<cnt<<".."<<endl;
int ans=0;
for(int i=1;i<=cnt;++i)
{
int minn=999999999;
int pos;
int nn;
for(int j=1;j<=num;++j)
{
int nn=0;
if(v[j]==i)
{
nn++;
if(dis[j][1]<minn)minn=dis[j][1],pos=j;
}
}
if(minn!=999999999)ans+=minn;
ans+=prime(i,pos,nn);
ff1[i]=pos;
}
//cout<<ff1[cnt]<<endl;
int kk=cnt;
for(int j=head[1];j;j=next[j])
{
int xx=ver[j];//边的终点
int vv=dfs2(xx);
if(edge[j]<vv)
{
//cout<<edge[j]<<" "<<vv<<endl;
ans=ans+edge[j]-vv;
kk++;
if(kk==s)break;
}
}
cout<<"Total miles driven: "<<ans<<endl;
}
}
//提交时稍作修改,scanf......
#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include<algorithm>
#include <set>
#include <queue>
#include <stack>
#include<vector>
#include<map>
#include<ctime>
#define ll long long
using namespace std;
const int N=36;
const int M=36*36;
int v[N];//联通块标号
int ver[M];//邻接表边M的终点
int edge[N*N];//邻接表边M的权值
int head[N];//邻接表点N的最后一条边
int next[M];//邻接表边M的下一条边
int tot;//邻接表 中边数
int cnt;//联通块的数目
int ff1[N];
int ff2[N];
int ff3[N];
void add(int x,int y,int z)//邻接表加边
{
ver[++tot]=y;
edge[tot]=z;
next[tot]=head[x];
head[x]=tot;
}
void dfs(int x)//得到x所在的联通块
{
v[x]=cnt;
for(int i=head[x];i!=-1;i=next[i])
{
int y=ver[i];
if(v[y])continue;
dfs(y);
}
}
int dis[N][N];
map<string,int>mm;
int num;
int d[N];//prime中以点N为终点的那条边;
bool flag[N];
int prime(int index,int pos,int nn)//联通块标号、起点
{
memset(d,0x3f,sizeof(d));
memset(flag,0,sizeof(flag));
d[pos]=0;
for(int i=1;i<nn;++i)
{
int x=0;
for(int j=1;j<=num;++j)
if(!flag[j]&&((x==0)||(d[j]<d[x]))&&v[j]==index)x=j;
flag[x]=1;
for(int j=head[x];j!=-1;j=next[j])
{
int y=ver[j];
if(!flag[y]&&v[y]==index)
{
if(edge[j]<d[y])
{
d[y]=edge[j];
ff2[y]=x;
}
d[y]=min(d[y],edge[j]);
}
}
}
int ans=0;
for(int i=1;i<=num;++i)
{
if(v[i]==index)ans+=d[i];
}
return ans;
}
int dfs2(int xx)//找1->xx的最长边
{
int ans=0;
for(int i=xx;i!=ff1[v[xx]];i=ff2[i])
{
ans=max(ans,dis[i][ff2[i]]);
}
return ans;
}
char ch1[110];
char ch2[110];
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
memset(dis,0,sizeof(dis));
tot=cnt=0;
mm.clear();
memset(v,0,sizeof(v));
memset(ver,0,sizeof(ver));
memset(head,0,sizeof(head));
memset(next,-1,sizeof(next));
memset(edge,0,sizeof(edge));
string str,t;
int x;
mm.insert(make_pair("Park",1 ));
num++;
getchar();
for(int i=1;i<=n;++i)
{
scanf("%s",ch1);
getchar();
scanf("%s",ch2);
getchar();
scanf("%d",&x);
str=ch1;
t=ch2;
//cin>>str>>t>>x;
int d1,d2;
if(mm.find(str)==mm.end())
{
num++;
mm.insert(make_pair(str,num));
d1=num;
}
else
{
d1=mm.find(str)->second;
}
if(mm.find(t)==mm.end())
{
num++;
mm.insert(make_pair(t,num));
d2=num;
}
else
{
d2=mm.find(t)->second;
}
dis[d1][d2]=dis[d2][d1]=x;
add(d1,d2,x);
add(d2,d1,x);
}
int s;
scanf("%d",&s);
for(int i=2;i<=num;++i)
{
if(v[i])continue;
cnt++;
dfs(i);
}
//cout<<cnt<<".."<<endl;
int ans=0;
for(int i=1;i<=cnt;++i)
{
int minn=0X3F;
int pos;
int nn;
for(int j=1;j<=num;++j)
{
int nn=0;
if(v[j]==i)
{
nn++;
if(dis[j][1]<minn)minn=dis[j][1],pos=j;
}
}
if(minn!=999999999)ans+=minn;
ans+=prime(i,pos,nn);
ff1[i]=pos;
}
//cout<<ff1[cnt]<<endl;
int kk=cnt;
for(int j=head[1];j!=-1;j=next[j])
{
int xx=ver[j];//边的终点
int vv=dfs2(xx);
if(edge[j]<vv)
{
//cout<<edge[j]<<" "<<vv<<endl;
ans=ans+edge[j]-vv;
kk++;
if(kk==s)break;
}
}
printf("Total miles driven: %d\n",ans);
//cout<<""<<ans<<endl;
}
return 0;
}