PTA—畅通工程之局部最小花费问题
直达链接点我!!!
思路
- 开始一直想DFS的思路…然后发现毕竟是多条道路都要试…然后遍历起来麻烦,保存最小花费也麻烦…pass
- 然后就是Dijkstra了…不过只能解决一个节点到其他节点的…这样其实也可以,毕竟畅通就是全部都连通了,那么就可以保存一个最小的dis数组(表示从开始这个点到其他所有点的最小花费)…但是…可能会重复花费…
- 后来想了想,并查集可以先将已经建好的道路先并起来,然后找最小的花费(直接按花费从小到大排序,用一个结构体保存输入的未建成的边),如果他俩没连通,那么这样就是最低花费了,连通起来,再去判断其他的边…
AC代码
#include <iostream>
#include <algorithm>
using namespace std;
struct way
{
int x,y;
int mon;
};
bool cmp(way a, way b)
{
return a.mon < b.mon;
}
int a[105];
int Find(int x)
{
if(x == a[x])
return x;
return a[x] = Find(a[x]);
}
bool merge(int x,int y)
{
x = Find(x);
y = Find(y);
if(x != y)
{
a[y] = x;
return false;
}
return true;
}
void ini(int n)
{
for(int i=1;i<=n;i++)
a[i] = i;
}
int main()
{
int n,i,j,count = 1;
scanf("%d",&n);
way b[(n-1)*n/2];
ini(n);
int top = 0;
for(i=0;i<n*(n-1)/2;i++)
{
int x,y,m,c;
scanf("%d %d %d %d",&x,&y,&m,&c);
if(c == 1 && !merge(x,y))
count++;
else
{
b[top].x = x;
b[top].y = y;
b[top].mon = m;
top++;
}
}
if(count == n)
{
printf("0");
return 0;
}
sort(b,b+top,cmp);
int sum = 0;
for(i=0;i<top;i++)
{
int x = b[i].x;
int y = b[i].y;
if(!merge(x,y))
{
count++;
sum += b[i].mon;
}
if(count == n)
break;
}
printf("%d",sum);
return 0;
}