繼續暢通工程
阿新 • • 發佈:2018-12-18
省政府“暢通工程”的目標是使全省任何兩個村莊間都可以實現公路交通(但不一定有直接的公路相連,只要能間接通過公路可達即可)。現得到城鎮道路統計表,表中列出了任意兩城鎮間修建道路的費用,以及該道路是否已經修通的狀態。現請你編寫程式,計算出全省暢通需要的最低成本。
Input
測試輸入包含若干測試用例。每個測試用例的第1行給出村莊數目N ( 1< N < 100 );隨後的 N(N-1)/2 行對應村莊間道路的成本及修建狀態,每行給4個正整數,分別是兩個村莊的編號(從1編號到N),此兩村莊間道路的成本,以及修建狀態:1表示已建,0表示未建。 當N為0時輸入結束。
Output
每個測試用例的輸出佔一行,輸出全省暢通需要的最低成本。
Sample Input
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
Sample Output
3 1 0
題目分析:這個題和hdu 1233差不多,就是加了一個狀態,因此我們可以先判斷每條路的狀態,如果是修好的,就讓它們的成本是0;如果沒修,就讓成本給出的成本。這樣問題的處理就和1233一樣了。
C++版本一
#include <iostream> #include <stdio.h> #include <algorithm> using namespace std; const int N=10000+10; int m,n,pre[N]; struct node{ int f,t,l,s; node (){}; node (int a ,int b ,int c,int d){ f=a; t=b; l=c; s=d; } bool operator <(const node &S)const{ if(s==S.s) return l<S.l; return s>S.s; } }e[N]; int find(int x){ int r=x; while(pre[r]!=r) r=pre[r]; return r; } void join(int x,int y){ int fx=find(x); int fy=find(y); if(fx!=fy) pre[fx]=fy; } int main() { while(scanf("%d",&n)!=EOF&&n){ int a,b,c,d; m=(n*(n-1))/2; for(int i=1;i<=m;i++){ scanf("%d%d%d%d",&a,&b,&c,&d); e[i]=node(a,b,c,d); } sort(e+1,e+m+1); for(int i=1;i<=n;i++) pre[i]=i; int ans=0; for(int i=1;i<=m;i++) if(find(e[i].f)!=find(e[i].t)){ join(e[i].f,e[i].t); if(e[i].s==0) ans+=e[i].l; } cout << ans << endl; } //cout << "Hello world!" << endl; return 0; }
C++版本二
#include<cstdio> #include<algorithm> using namespace std; int f[105]; int n; struct node { int vil_o, vil_t, way_cost, way_f; }a[5005];//定義結構體 int find(int x) { if (x != f[x]) f[x] = find(f[x]); return f[x]; } bool join (int x, int y) { int fx = find(x); int fy = find(y); if (fx == fy) return 0; f[fx] = fy; return 1; } int cmp(node a, node b) { return a.way_cost < b.way_cost; }//成本按升序排列 void itoa() { for (int i = 1; i <= n; i ++) f[i] = i; }//初始化 int main() { while (~scanf ("%d", &n) && n) { int ans = n * (n - 1) / 2; for (int i = 0; i < ans; i ++) { scanf ("%d %d %d %d", &a[i].vil_o, &a[i].vil_t, &a[i].way_cost, &a[i].way_f); if (a[i].way_f == 1) { a[i].way_cost = 0; f[a[i].vil_o] = a[i].vil_t;//當道路修通時,規定一節點為另一節點的父親 } //如果路的狀態已修建則該段路成本為零 } sort(a, a + ans, cmp);//這裡錯了好多次,就是ans寫成了n,太粗心了 itoa(); int sum = 0; for (int i = 0; i < ans; i ++) { if (join (a[i].vil_o, a[i].vil_t)) sum += a[i].way_cost; } printf("%d\n", sum); } return 0; }
C++版本三
prim演算法
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define inf 0x3f3f3f3f
int adj[100];
int vis[100];
int nearest[100];
int map[100][100];
int n,m;
int prim()
{
int i,j,min;
int ans=0;
vis[1]=1;
for(i=2;i<=n;i++)
{
nearest[i]=map[1][i];
adj[i]=1;
}
int cnt=n-1;
while(cnt--)
{
min=inf;
j=1;
for(i=1;i<=n;i++)
{
if(!vis[i]&&nearest[i]<min)
{
min=nearest[i];
j=i;
}
}
ans+=map[j][adj[j]];
vis[j]=1;
for(i=1;i<=n;i++)
{
if(!vis[i]&&map[i][j]<nearest[i])
{
nearest[i]=map[i][j];
adj[i]=j;
}
}
}
return ans;
}
int main()
{
int i;
while(~scanf("%d",&n)&&n)
{
int b,c,d,sta;
memset(vis,0,sizeof(vis));
memset(map,inf,sizeof(map));
m=n*(n-1)/2;
for(i=0;i<m;i++)
{
scanf("%d%d%d%d",&b,&c,&d,&sta);
if(sta==0)
map[b][c]=map[c][b]=d;
else
map[b][c]=map[c][b]=0;
}
int sum=prim();
printf("%d\n",sum);
}
return 0;
}