您的位置:首页 > 其它

继续畅通工程

2015-07-27 20:06 369 查看
[align=left]Problem Description[/align]
省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可)。现得到城镇道路统计表,表中列出了任意两城镇间修建道路的费用,以及该道路是否已经修通的状态。现请你编写程序,计算出全省畅通需要的最低成本。

 

[align=left]Input[/align]
测试输入包含若干测试用例。每个测试用例的第1行给出村庄数目N ( 1< N < 100 );随后的 N(N-1)/2 行对应村庄间道路的成本及修建状态,每行给4个正整数,分别是两个村庄的编号(从1编号到N),此两村庄间道路的成本,以及修建状态:1表示已建,0表示未建。

当N为0时输入结束。
 

[align=left]Output[/align]
每个测试用例的输出占一行,输出全省畅通需要的最低成本。
 

[align=left]Sample Input[/align]

3
1 2 1 0
1 3 2 0
2 3 4 0
3
1 2 1 0
1 3 2 0
2 3 4 1
3
1 2 1 0
1 3 2 1
2 3 4 1
0

 

[align=left]Sample Output[/align]

3
1
0

 
[align=left]题解:最小生成树3种做法。把存在的费用设置为0就解决了存在的公路问题。因为如果存在的公路是最小生成树的边,那么我就+0,。[/align]
[align=left]
[/align]
普里姆优化做法:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>

using namespace std; //327ms ,vector耗时间

const int INF = 105;

struct Node
{
int to;
int cost;
Node(){}
Node(int a,int b)
{
to = a;
cost = b;
}
bool operator< (Node t) const
{
return cost > t.cost;
}
};

priority_queue<Node> q;
vector<Node> vec[INF];
bool visited[INF];
int ans;

void prim(int n)
{
memset(visited,false,sizeof(visited));
ans = 0;
for(int i = 0;i < vec[1].size();i++) //从1开始
{
q.push(vec[1][i]);
}
visited[1] = true;

int cnt = 0;
while(!q.empty() && cnt < n -1)  //找到n-1条边
{
Node t = q.top();
q.pop();
if(visited[t.to])       //访问过
{
continue;
}
ans += t.cost;
visited[t.to] = true;
cnt++;
for(int i = 0;i < vec[t.to].size();i++) //更新队列
{
if(!visited[vec[t.to][i].to])
{
q.push(vec[t.to][i]);
}
}
}

printf("%d\n",ans);

for(int i = 1;i <= n;i++)
{
vec[i].clear();
}
while(!q.empty())
{
q.pop();
}
}

int main()
{
int n;
int u,v,c,s;
while(scanf("%d",&n) && n != 0)
{
for(int i = 0;i < n * (n - 1) / 2;i++)
{
scanf("%d%d%d%d",&u,&v,&c,&s);
if(0 == s)
{
vec[u].push_back(Node(v,c));
vec[v].push_back(Node(u,c));
}
else
{
vec[u].push_back(Node(v,0));
vec[v].push_back(Node(u,0));
}
}

prim(n);
}

return 0;
}

[align=left]
[/align]
普里姆:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>

using namespace std;    //运行时间327ms

const int INF = 0x3fffffff;

int map[101][105];
bool visited[105];
int e[105];
int ans;

void prim(int n)
{
memset(visited,false,sizeof(visited));
ans = 0;
for(int i = 1;i <= n;i++)
{
e[i] = map[1][i];      //从1开始找
}
e[1] = 0;
visited[1] = true;

for(int i = 1;i < n;i++) //找n-1条边
{
int min = INF;
int k;
for(int j = 1;j <= n;j++)
{
if(!visited[j] && min > e[j])  //找到最小边
{
min = e[j];
k = j;
}
}

ans += min;       //找到了一条
visited[k] = true;

for(int j = 1;j <= n;j++)     //更新数组最小值
{
if(!visited[j] && e[j] > map[k][j])
{
e[j] = map[k][j];
}
}
}

printf("%d\n",ans);
}

int main()
{
int n;
int u,v,c,s;
while(scanf("%d",&n) && n != 0)
{
for(int i = 0;i < n * (n - 1) / 2;i++)
{
scanf("%d%d%d%d",&u,&v,&c,&s);
if(0 == s)
{
map[u][v] = c;
map[v][u] = c;
}
else
{
map[u][v] = 0;      //表示不需要花费钱了
map[v][u] = 0;
}
}

prim(n);
}

return 0;
}

[align=left]
[/align]
克鲁斯卡尔:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <algorithm>

using namespace std;     //运行时间493ms

struct Node
{
int u;
int v;
int cost;
Node(){}
Node(int a,int b,int c)
{
u = a;
v = b;
cost = c;
}
bool operator< (Node t) const
{
return cost < t.cost;
}
};

Node e[10005];
bool visited[105];
int fa[105];
int ans;

int find(int x)  //并查集
{
if(x == fa[x])
{
return x;
}

return fa[x] = find(fa[x]);
}

void kruskal(int n)
{
sort(e,e + n * (n - 1) / 2); //排序后找最小边

int k = 0;
for(int i = 1;i < n;i++)      //n-1条边
{
for(int j = k;j < n * (n - 1) / 2;j++)
{
int x = find(e[j].u);
int y = find(e[j].v);
if(x == y)              //判断是不是同一个集合
{
continue;
}
fa[x] = y;            //加入同一个集合
visited[e[j].u] = true;
visited[e[j].v] = true;
ans += e[j].cost;
k = j + 1;
break;
}
}

printf("%d\n",ans);
}

int main()
{
int n;
int u,v,c,s;
while(scanf("%d",&n) && n != 0)
{
ans = 0;
int k = 0;
for(int i = 0;i < n * (n - 1) / 2;i++)
{
scanf("%d%d%d%d",&u,&v,&c,&s);
if(0 == s)
{
e[k++] = Node(u,v,c);
}
else
{
e[k++] = Node(u,v,0);    //0表示修建了该路,所以不需要成本
}
}

for(int i = 1;i <= n;i++)
{
fa[i] = i;
}

memset(visited,false,sizeof(visited));
kruskal(n);
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: