您的位置:首页 > 其它

畅通工程系列问题题解(HDU 1233 1863 1875 1879)

2016-04-07 21:49 537 查看
HDU 1233

krusal

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
#define maxnum 5051

int n,line;//sum为最小权之和,n为顶点个数,line为边数
int cnt;
int par[maxnum];
double sum;

struct node
{
int u,v;
double w;
}list[maxnum];

int cmp(node a,node b)
{
return a.w < b.w;
}

int find(int x)//并查集的路径压缩
{
if(par[x] == -1)
return x;
return par[x] = find(par[x]);
}

void kruskal()
{
int i,j;

sort(list,list+line,cmp);

for(i=0,sum=0;i<line;i++)
{
int x = find(list[i].u);
int y = find(list[i].v);
if(x != y)
{
sum += list[i].w;
cnt++;
par[x] = y;
}

if(cnt == n-1)
break;
}
}

int main()
{
int i,j;
int vis;
double len;
int t;

while(scanf("%d",&n),n)
{
memset(par,-1,sizeof(par));
line = n*(n-1)/2;
for(i=0;i<line;i++)
{
scanf("%d%d%lf",&list[i].u,&list[i].v,&list[i].w);
}

cnt=0;
kruskal();

cout<<sum<<endl;
}

return 0;
}


HDU 1863

krusal

#include <iostream>
#include <queue>
#include <map>
#include <cstring>
#include <algorithm>
using namespace std;
#define maxnum 105

int sum,n,line;//sum为最小权之和,n为顶点个数,line为边数
int u[maxnum],v[maxnum],w[maxnum],r[maxnum],p[maxnum];//u起点,v终点,w权值

int cmp(const int i,const int j)
{
return w[i] < w[j];
}

int find(int x)//并查集的路径压缩
{
return p[x]==x?x:p[x]=find(p[x]);
}

int kruskal()
{
int i,j,k;
int cnt = 0;

for(i=0;i<line;i++)
r[i] = i;
for(i=0;i<n;i++)
p[i] = i;

sort(r,r+line,cmp);

for(i=0,sum=0;i<line;i++)
{
int x = find(u[r[i]]);
int y = find(v[r[i]]);
if(x != y)
{
sum += w[r[i]];
cnt++;
p[x] = y;
}
}

if(cnt != n-1)
sum = 0;
return sum;
}

int main()
{
int i,j,k;
int len;
int t,s,d,p,q;

while(cin>>line>>n,line)
{
for(i=0;i<line;i++)
{
cin>>u[i]>>v[i]>>w[i];
}

t = kruskal();

if(t)
cout<<t<<endl;
else
cout<<"?"<<endl;
}

return 0;
}


hdu 1875

代码一 krusal 100+ms

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;

int n;//sum为最小权之和,n为顶点个数,line为边数
int cnt;
int par[101];
double sum;

struct node
{
int u;
int v;
double w;
}list[6000];

struct node2
{
double u,v;
}list2[101];

int cmp(node a,node b)
{
return a.w < b.w;
}

int find(int x)//并查集的路径压缩
{
if(par[x] == -1)
return x;
return par[x] = find(par[x]);
}

double kruskal(int line)
{
int i,j;

sort(list,list+line,cmp);

for(i=0,sum=0;i<line;i++)
{
int x = find(list[i].u);
int y = find(list[i].v);
if(x != y)
{
sum += list[i].w;
cnt++;
par[x] = y;
}

if(cnt == n-1)
return sum;
}

return 0;
}

int main()
{
int i,j,N,k,kk;
int vis,line;
int len;
int p,q;
double bian,t;

scanf("%d",&N);
while(N--)
{
scanf("%d",&n);
memset(par,-1,sizeof(par));

for(i=0,k=0;i<n;i++)
{
scanf("%lf%lf",&list2[i].u,&list2[i].v);
for(j=0;j<i;j++)
{
bian = sqrt(pow(fabs(list2[j].u-list2[i].u),2.0)+fabs(pow(list2[j].v-list2[i].v,2.0)));
if(bian >= 10 && bian <= 1000)
{
list[k].u = j+1;
list[k].v = i+1;
list[k++].w = bian;
}
}
}

cnt = 0;
t = kruskal(k);

if(t)
printf("%.1lf\n",t*100);
else
cout<<"oh!"<<endl;
}

return 0;
}
代码二Prim 优先队列 60+ms

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
using namespace std;

int n;//sum为最小权之和,n为顶点个数,line为边数
int cnt;
int par[101];
int link[101][101];
double c[101][101];
int yiwei[101];
int vis[6001];
double sum;

struct node
{
int u;
int v;
double w;
};

struct node2
{
double u,v;
}list2[101];

bool operator < (const node &a,const node &b)
{
return a.w > b.w;
}

int prim(int s)
{
int i,j,k,m,t,u,total;

memset(vis,0,sizeof(vis));
priority_queue <node> qq;

struct node nn;

total  = 1;
vis[s] = 1;
sum = 0;
while(total < n)
{
for(i=1;i<link[s][0];i++)
{
if(!vis[link[s][i]])
{
nn.u = s;
nn.v = link[s][i];
nn.w = c[s][nn.v];
qq.push(nn);
}
}

while(!qq.empty() && vis[qq.top().v])//遇到顶点和集合外的顶点没有相连的
qq.pop();//刚巧这个点作为终点是最短的,因为这个顶点没背标记过,所以会错误的计入在内

if(qq.empty())
break;

nn = qq.top();
s = nn.v;
sum += nn.w;
vis[s] = 1;//标记为集合内的元素
qq.pop();
total++;
}

if(total == n)
return 1;
else
return 0;
}

int main()
{
int i,j,N,k,kk;
int vis,line;
int len;
int p,q;
double bian,t;

scanf("%d",&N);
while(N--)
{
scanf("%d",&n);
memset(par,-1,sizeof(par));

for(i=1,k=0;i<=n;i++)
{
link[i][0] = 1;
scanf("%lf%lf",&list2[i].u,&list2[i].v);
for(j=1;j<i;j++)
{
bian = sqrt(pow(fabs(list2[j].u-list2[i].u),2.0)+fabs(pow(list2[j].v-list2[i].v,2.0)));
if(bian >= 10 && bian <= 1000)
{
c[j][i] = c[i][j] = bian;
link[i][link[i][0]++] = j;
link[j][link[j][0]++] = i;
}
}
}

cnt = 0;

kk = prim(1);

if(kk)
printf("%.1lf\n",sum*100);
else
cout<<"oh!"<<endl;
}

return 0;
}


HDU 1879

krusal+并查集

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
#define maxnum 5051

int n;//sum为最小权之和,n为顶点个数,line为边数
int cnt;
int par[maxnum];
int sum;

struct node
{
int u,v;
double w;
}list[maxnum];

struct node2
{
int u,w;
}list2[maxnum];

int cmp(node a,node b)
{
return a.w < b.w;
}

int find(int x)//并查集的路径压缩
{
if(par[x] == -1)
return x;
return par[x] = find(par[x]);
}

int kruskal(int line)
{
int i,j;

sort(list,list+line,cmp);

for(i=0,sum=0;i<line;i++)
{
int x = find(list[i].u);
int y = find(list[i].v);
if(x != y)
{
sum += list[i].w;
cnt++;
par[x] = y;
}

if(cnt == n-1)
return sum;
}

return 0;
}

int fun(int kk)
{
int i;
for(i=0;i<kk;i++)
{
int x = find(list2[i].u);
int y = find(list2[i].w);
if(x != y)
{
cnt++;
par[x] = y;
}

if(cnt == n-1)
return 1;
}

return 0;
}

int main()
{
int i,j,k,kk;
int vis,line;
int len;
int t,p,tt,q;

while(scanf("%d",&n),n)
{
k = kk = 0;
memset(par,-1,sizeof(par));
line = n*(n-1)/2;
for(i=0;i<line;i++)
{
scanf("%d%d%d%d",&p,&q,&len,&vis);
if(vis)
{
list2[kk].u = p;
list2[kk++].w = q;
}
else
{
list[k].u = p;
list[k].v = q;
list[k++].w = len;
}
}

cnt=t=tt=0;

if(kk)
tt = fun(kk);

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