搜索与回溯算法
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#include<map>
map<string,int>ggbond;
struct node
{
int a,b,c;
}ai[2000000];
int f[2000000];
int m,n,ans,res=0x3f3f3f3f;
int d[2000000],qi,qk;
bool cmp(node a,node b);
int find(int x);
void dfs(int a);
int main()
{
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
string a,b;int c;
cin>>a>>b>>c;
if(!ggbond.count(a))ggbond[a]=++n;
if(!ggbond.count(b))ggbond[b]=++n;
ai[i].a=ggbond[a],ai[i].b=ggbond[b],ai[i].c=c;
}
qk=ggbond["Park"];
for(int i=1;i<=n;i++)
f[i]=i;
sort(ai+1,ai+1+m,cmp);
scanf("%d",&qi);
dfs(1);
cout<<"Total miles driven: "<<res;
}
void dfs(int i)
{
if(d[qk]>qi)
return ;
int gg=1;
for(int i=1;i<n;i++)
if(find(i)!=find(i+1))gg=0;
if(gg)
{
res=min(res,ans);
return ;
}
if(i==m+1)
return ;
int a=find(ai[i].a);
int b=find(ai[i].b);
if(a==b)
{
dfs(i+1);
return ;
}
d[ai[i].b]++;
d[ai[i].a]++;
f[a]=b;
ans+=ai[i].c;
dfs(i+1);
ans-=ai[i].c;
f[a]=a;
d[ai[i].b]--;
d[ai[i].a]--;
if(ai[i].a==qk||ai[i].b==qk)
dfs(i+1);
}
bool cmp(node a,node b)
{
return a.c<b.c;
}
int find(int x)
{
if(f[x]==x)
return f[x];
return find(f[x]);
}
解析
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#include<map>
map<string,int>ggbond;
struct node
{
int a,b,c;
}ai[2000000];//结构体记录边
int f[2000000];
int m,n,ans,res=0x3f3f3f3f;
int d[2000000],qi,qk;
bool cmp(node a,node b);
int find(int x);
void dfs(int a);
int main()
{
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
string a,b;int c;
cin>>a>>b>>c;
if(!ggbond.count(a))ggbond[a]=++n;
if(!ggbond.count(b))ggbond[b]=++n;//map记录点的编号
ai[i].a=ggbond[a],ai[i].b=ggbond[b],ai[i].c=c;
}
qk=ggbond["Park"];//记录Park的编号
for(int i=1;i<=n;i++)
f[i]=i;
sort(ai+1,ai+1+m,cmp);
scanf("%d",&qi);
dfs(1);
cout<<"Total miles driven: "<<res;
}
void dfs(int i)
{
if(d[qk]>qi)
return ;//如果停车过多,返回
int gg=1;
for(int i=1;i<n;i++)
if(find(i)!=find(i+1))gg=0;
if(gg)//如果每个点的find()均相同,则是可行解
{
res=min(res,ans);
return ;
}
if(i==m+1)//i不能超过m+1;
return ;
int a=find(ai[i].a);
int b=find(ai[i].b);
if(a==b)
{
dfs(i+1);//如果他们的find()相同,则跳过
return ;
}
d[ai[i].b]++;
d[ai[i].a]++;
f[a]=b;
ans+=ai[i].c;
dfs(i+1);
//以下为回溯
ans-=ai[i].c;
f[a]=a;
d[ai[i].b]--;
d[ai[i].a]--;
if(ai[i].a==qk||ai[i].b==qk)//如果与Park相连,选择一遍,不选一遍
dfs(i+1);
}
bool cmp(node a,node b)
{
return a.c<b.c;
}
int find(int x)
{
if(f[x]==x)
return f[x];
return find(f[x]);//这里不能写作f[x]=find(f[x]),否则无法回溯;
}
作者:马良
链接:https://www.acwing.com/solution/content/57107/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。